6213 lines · c
1//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//2//3// 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-exception6//7//===----------------------------------------------------------------------===//8//9// Generic itanium demangler library.10// There are two copies of this file in the source tree. The one under11// libcxxabi is the original and the one under llvm is the copy. Use12// cp-to-llvm.sh to update the copy. See README.txt for more details.13//14//===----------------------------------------------------------------------===//15 16#ifndef DEMANGLE_ITANIUMDEMANGLE_H17#define DEMANGLE_ITANIUMDEMANGLE_H18 19#include "DemangleConfig.h"20#include "StringViewExtras.h"21#include "Utility.h"22#include <algorithm>23#include <cctype>24#include <cstdint>25#include <cstdio>26#include <cstdlib>27#include <cstring>28#include <limits>29#include <new>30#include <string_view>31#include <type_traits>32#include <utility>33 34#if defined(__clang__)35#pragma clang diagnostic push36#pragma clang diagnostic ignored "-Wunused-template"37#endif38 39DEMANGLE_NAMESPACE_BEGIN40 41template <class T, size_t N> class PODSmallVector {42 static_assert(std::is_trivially_copyable<T>::value,43 "T is required to be a trivially copyable type");44 static_assert(std::is_trivially_default_constructible<T>::value,45 "T is required to be trivially default constructible");46 T *First = nullptr;47 T *Last = nullptr;48 T *Cap = nullptr;49 T Inline[N] = {};50 51 bool isInline() const { return First == Inline; }52 53 void clearInline() {54 First = Inline;55 Last = Inline;56 Cap = Inline + N;57 }58 59 void reserve(size_t NewCap) {60 size_t S = size();61 if (isInline()) {62 auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));63 if (Tmp == nullptr)64 std::abort();65 std::copy(First, Last, Tmp);66 First = Tmp;67 } else {68 First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));69 if (First == nullptr)70 std::abort();71 }72 Last = First + S;73 Cap = First + NewCap;74 }75 76public:77 PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}78 79 PODSmallVector(const PODSmallVector &) = delete;80 PODSmallVector &operator=(const PODSmallVector &) = delete;81 82 PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {83 if (Other.isInline()) {84 std::copy(Other.begin(), Other.end(), First);85 Last = First + Other.size();86 Other.clear();87 return;88 }89 90 First = Other.First;91 Last = Other.Last;92 Cap = Other.Cap;93 Other.clearInline();94 }95 96 PODSmallVector &operator=(PODSmallVector &&Other) {97 if (Other.isInline()) {98 if (!isInline()) {99 std::free(First);100 clearInline();101 }102 std::copy(Other.begin(), Other.end(), First);103 Last = First + Other.size();104 Other.clear();105 return *this;106 }107 108 if (isInline()) {109 First = Other.First;110 Last = Other.Last;111 Cap = Other.Cap;112 Other.clearInline();113 return *this;114 }115 116 std::swap(First, Other.First);117 std::swap(Last, Other.Last);118 std::swap(Cap, Other.Cap);119 Other.clear();120 return *this;121 }122 123 // NOLINTNEXTLINE(readability-identifier-naming)124 void push_back(const T &Elem) {125 if (Last == Cap)126 reserve(size() * 2);127 *Last++ = Elem;128 }129 130 // NOLINTNEXTLINE(readability-identifier-naming)131 void pop_back() {132 DEMANGLE_ASSERT(Last != First, "Popping empty vector!");133 --Last;134 }135 136 void shrinkToSize(size_t Index) {137 DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");138 Last = First + Index;139 }140 141 T *begin() { return First; }142 T *end() { return Last; }143 144 bool empty() const { return First == Last; }145 size_t size() const { return static_cast<size_t>(Last - First); }146 T &back() {147 DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");148 return *(Last - 1);149 }150 T &operator[](size_t Index) {151 DEMANGLE_ASSERT(Index < size(), "Invalid access!");152 return *(begin() + Index);153 }154 void clear() { Last = First; }155 156 ~PODSmallVector() {157 if (!isInline())158 std::free(First);159 }160};161 162class NodeArray;163 164// Base class of all AST nodes. The AST is built by the parser, then is165// traversed by the printLeft/Right functions to produce a demangled string.166class Node {167public:168 enum Kind : uint8_t {169#define NODE(NodeKind) K##NodeKind,170#include "ItaniumNodes.def"171 };172 173 /// Three-way bool to track a cached value. Unknown is possible if this node174 /// has an unexpanded parameter pack below it that may affect this cache.175 enum class Cache : uint8_t { Yes, No, Unknown, };176 177 /// Operator precedence for expression nodes. Used to determine required178 /// parens in expression emission.179 enum class Prec : uint8_t {180 Primary,181 Postfix,182 Unary,183 Cast,184 PtrMem,185 Multiplicative,186 Additive,187 Shift,188 Spaceship,189 Relational,190 Equality,191 And,192 Xor,193 Ior,194 AndIf,195 OrIf,196 Conditional,197 Assign,198 Comma,199 Default,200 };201 202private:203 Kind K;204 205 Prec Precedence : 6;206 207protected:208 /// Tracks if this node has a component on its right side, in which case we209 /// need to call printRight.210 Cache RHSComponentCache : 2;211 212 /// Track if this node is a (possibly qualified) array type. This can affect213 /// how we format the output string.214 Cache ArrayCache : 2;215 216 /// Track if this node is a (possibly qualified) function type. This can217 /// affect how we format the output string.218 Cache FunctionCache : 2;219 220public:221 Node(Kind K_, Prec Precedence_ = Prec::Primary,222 Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,223 Cache FunctionCache_ = Cache::No)224 : K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),225 ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}226 Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,227 Cache FunctionCache_ = Cache::No)228 : Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,229 FunctionCache_) {}230 231 /// Visit the most-derived object corresponding to this object.232 template<typename Fn> void visit(Fn F) const;233 234 // The following function is provided by all derived classes:235 //236 // Call F with arguments that, when passed to the constructor of this node,237 // would construct an equivalent node.238 //template<typename Fn> void match(Fn F) const;239 240 bool hasRHSComponent(OutputBuffer &OB) const {241 if (RHSComponentCache != Cache::Unknown)242 return RHSComponentCache == Cache::Yes;243 return hasRHSComponentSlow(OB);244 }245 246 bool hasArray(OutputBuffer &OB) const {247 if (ArrayCache != Cache::Unknown)248 return ArrayCache == Cache::Yes;249 return hasArraySlow(OB);250 }251 252 bool hasFunction(OutputBuffer &OB) const {253 if (FunctionCache != Cache::Unknown)254 return FunctionCache == Cache::Yes;255 return hasFunctionSlow(OB);256 }257 258 Kind getKind() const { return K; }259 260 Prec getPrecedence() const { return Precedence; }261 Cache getRHSComponentCache() const { return RHSComponentCache; }262 Cache getArrayCache() const { return ArrayCache; }263 Cache getFunctionCache() const { return FunctionCache; }264 265 virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }266 virtual bool hasArraySlow(OutputBuffer &) const { return false; }267 virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }268 269 // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to270 // get at a node that actually represents some concrete syntax.271 virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }272 273 // Print this node as an expression operand, surrounding it in parentheses if274 // its precedence is [Strictly] weaker than P.275 void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,276 bool StrictlyWorse = false) const {277 bool Paren =278 unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);279 if (Paren)280 OB.printOpen();281 print(OB);282 if (Paren)283 OB.printClose();284 }285 286 void print(OutputBuffer &OB) const {287 OB.printLeft(*this);288 if (RHSComponentCache != Cache::No)289 OB.printRight(*this);290 }291 292 // Print an initializer list of this type. Returns true if we printed a custom293 // representation, false if nothing has been printed and the default294 // representation should be used.295 virtual bool printInitListAsType(OutputBuffer &, const NodeArray &) const {296 return false;297 }298 299 virtual std::string_view getBaseName() const { return {}; }300 301 // Silence compiler warnings, this dtor will never be called.302 virtual ~Node() = default;303 304#ifndef NDEBUG305 DEMANGLE_DUMP_METHOD void dump() const;306#endif307 308private:309 friend class OutputBuffer;310 311 // Print the "left" side of this Node into OutputBuffer.312 //313 // Note, should only be called from OutputBuffer implementations.314 // Call \ref OutputBuffer::printLeft instead.315 virtual void printLeft(OutputBuffer &) const = 0;316 317 // Print the "right". This distinction is necessary to represent C++ types318 // that appear on the RHS of their subtype, such as arrays or functions.319 // Since most types don't have such a component, provide a default320 // implementation.321 //322 // Note, should only be called from OutputBuffer implementations.323 // Call \ref OutputBuffer::printRight instead.324 virtual void printRight(OutputBuffer &) const {}325};326 327class NodeArray {328 Node **Elements;329 size_t NumElements;330 331public:332 NodeArray() : Elements(nullptr), NumElements(0) {}333 NodeArray(Node **Elements_, size_t NumElements_)334 : Elements(Elements_), NumElements(NumElements_) {}335 336 bool empty() const { return NumElements == 0; }337 size_t size() const { return NumElements; }338 339 Node **begin() const { return Elements; }340 Node **end() const { return Elements + NumElements; }341 342 Node *operator[](size_t Idx) const { return Elements[Idx]; }343 344 void printWithComma(OutputBuffer &OB) const {345 bool FirstElement = true;346 for (size_t Idx = 0; Idx != NumElements; ++Idx) {347 size_t BeforeComma = OB.getCurrentPosition();348 if (!FirstElement)349 OB += ", ";350 size_t AfterComma = OB.getCurrentPosition();351 Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);352 353 // Elements[Idx] is an empty parameter pack expansion, we should erase the354 // comma we just printed.355 if (AfterComma == OB.getCurrentPosition()) {356 OB.setCurrentPosition(BeforeComma);357 continue;358 }359 360 FirstElement = false;361 }362 }363 364 // Print an array of integer literals as a string literal. Returns whether we365 // could do so.366 bool printAsString(OutputBuffer &OB) const;367};368 369struct NodeArrayNode : Node {370 NodeArray Array;371 NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}372 373 template<typename Fn> void match(Fn F) const { F(Array); }374 375 void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }376};377 378class DotSuffix final : public Node {379 const Node *Prefix;380 const std::string_view Suffix;381 382public:383 DotSuffix(const Node *Prefix_, std::string_view Suffix_)384 : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}385 386 template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }387 388 void printLeft(OutputBuffer &OB) const override {389 Prefix->print(OB);390 OB += " (";391 OB += Suffix;392 OB += ")";393 }394};395 396class VendorExtQualType final : public Node {397 const Node *Ty;398 std::string_view Ext;399 const Node *TA;400 401public:402 VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)403 : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}404 405 const Node *getTy() const { return Ty; }406 std::string_view getExt() const { return Ext; }407 const Node *getTA() const { return TA; }408 409 template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }410 411 void printLeft(OutputBuffer &OB) const override {412 Ty->print(OB);413 OB += " ";414 OB += Ext;415 if (TA != nullptr)416 TA->print(OB);417 }418};419 420enum FunctionRefQual : unsigned char {421 FrefQualNone,422 FrefQualLValue,423 FrefQualRValue,424};425 426enum Qualifiers {427 QualNone = 0,428 QualConst = 0x1,429 QualVolatile = 0x2,430 QualRestrict = 0x4,431};432 433inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {434 return Q1 = static_cast<Qualifiers>(Q1 | Q2);435}436 437class QualType final : public Node {438protected:439 const Qualifiers Quals;440 const Node *Child;441 442 void printQuals(OutputBuffer &OB) const {443 if (Quals & QualConst)444 OB += " const";445 if (Quals & QualVolatile)446 OB += " volatile";447 if (Quals & QualRestrict)448 OB += " restrict";449 }450 451public:452 QualType(const Node *Child_, Qualifiers Quals_)453 : Node(KQualType, Child_->getRHSComponentCache(), Child_->getArrayCache(),454 Child_->getFunctionCache()),455 Quals(Quals_), Child(Child_) {}456 457 Qualifiers getQuals() const { return Quals; }458 const Node *getChild() const { return Child; }459 460 template<typename Fn> void match(Fn F) const { F(Child, Quals); }461 462 bool hasRHSComponentSlow(OutputBuffer &OB) const override {463 return Child->hasRHSComponent(OB);464 }465 bool hasArraySlow(OutputBuffer &OB) const override {466 return Child->hasArray(OB);467 }468 bool hasFunctionSlow(OutputBuffer &OB) const override {469 return Child->hasFunction(OB);470 }471 472 void printLeft(OutputBuffer &OB) const override {473 OB.printLeft(*Child);474 printQuals(OB);475 }476 477 void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); }478};479 480class ConversionOperatorType final : public Node {481 const Node *Ty;482 483public:484 ConversionOperatorType(const Node *Ty_)485 : Node(KConversionOperatorType), Ty(Ty_) {}486 487 template<typename Fn> void match(Fn F) const { F(Ty); }488 489 void printLeft(OutputBuffer &OB) const override {490 OB += "operator ";491 Ty->print(OB);492 }493};494 495class PostfixQualifiedType final : public Node {496 const Node *Ty;497 const std::string_view Postfix;498 499public:500 PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)501 : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}502 503 template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }504 505 void printLeft(OutputBuffer &OB) const override {506 OB.printLeft(*Ty);507 OB += Postfix;508 }509};510 511class NameType final : public Node {512 const std::string_view Name;513 514public:515 NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}516 517 template<typename Fn> void match(Fn F) const { F(Name); }518 519 std::string_view getName() const { return Name; }520 std::string_view getBaseName() const override { return Name; }521 522 void printLeft(OutputBuffer &OB) const override { OB += Name; }523};524 525class BitIntType final : public Node {526 const Node *Size;527 bool Signed;528 529public:530 BitIntType(const Node *Size_, bool Signed_)531 : Node(KBitIntType), Size(Size_), Signed(Signed_) {}532 533 template <typename Fn> void match(Fn F) const { F(Size, Signed); }534 535 void printLeft(OutputBuffer &OB) const override {536 if (!Signed)537 OB += "unsigned ";538 OB += "_BitInt";539 OB.printOpen();540 Size->printAsOperand(OB);541 OB.printClose();542 }543};544 545class ElaboratedTypeSpefType : public Node {546 std::string_view Kind;547 Node *Child;548public:549 ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)550 : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}551 552 template<typename Fn> void match(Fn F) const { F(Kind, Child); }553 554 void printLeft(OutputBuffer &OB) const override {555 OB += Kind;556 OB += ' ';557 Child->print(OB);558 }559};560 561class TransformedType : public Node {562 std::string_view Transform;563 Node *BaseType;564public:565 TransformedType(std::string_view Transform_, Node *BaseType_)566 : Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}567 568 template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }569 570 void printLeft(OutputBuffer &OB) const override {571 OB += Transform;572 OB += '(';573 BaseType->print(OB);574 OB += ')';575 }576};577 578struct AbiTagAttr : Node {579 Node *Base;580 std::string_view Tag;581 582 AbiTagAttr(Node *Base_, std::string_view Tag_)583 : Node(KAbiTagAttr, Base_->getRHSComponentCache(), Base_->getArrayCache(),584 Base_->getFunctionCache()),585 Base(Base_), Tag(Tag_) {}586 587 template<typename Fn> void match(Fn F) const { F(Base, Tag); }588 589 std::string_view getBaseName() const override { return Base->getBaseName(); }590 591 void printLeft(OutputBuffer &OB) const override {592 OB.printLeft(*Base);593 OB += "[abi:";594 OB += Tag;595 OB += "]";596 }597};598 599class EnableIfAttr : public Node {600 NodeArray Conditions;601public:602 EnableIfAttr(NodeArray Conditions_)603 : Node(KEnableIfAttr), Conditions(Conditions_) {}604 605 template<typename Fn> void match(Fn F) const { F(Conditions); }606 607 void printLeft(OutputBuffer &OB) const override {608 OB += " [enable_if:";609 Conditions.printWithComma(OB);610 OB += ']';611 }612};613 614class ObjCProtoName : public Node {615 const Node *Ty;616 std::string_view Protocol;617 618public:619 ObjCProtoName(const Node *Ty_, std::string_view Protocol_)620 : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}621 622 template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }623 624 bool isObjCObject() const {625 return Ty->getKind() == KNameType &&626 static_cast<const NameType *>(Ty)->getName() == "objc_object";627 }628 629 std::string_view getProtocol() const { return Protocol; }630 631 void printLeft(OutputBuffer &OB) const override {632 Ty->print(OB);633 OB += "<";634 OB += Protocol;635 OB += ">";636 }637};638 639class PointerType final : public Node {640 const Node *Pointee;641 642public:643 PointerType(const Node *Pointee_)644 : Node(KPointerType, Pointee_->getRHSComponentCache()),645 Pointee(Pointee_) {}646 647 const Node *getPointee() const { return Pointee; }648 649 template<typename Fn> void match(Fn F) const { F(Pointee); }650 651 bool hasRHSComponentSlow(OutputBuffer &OB) const override {652 return Pointee->hasRHSComponent(OB);653 }654 655 void printLeft(OutputBuffer &OB) const override {656 // We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.657 if (Pointee->getKind() != KObjCProtoName ||658 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {659 OB.printLeft(*Pointee);660 if (Pointee->hasArray(OB))661 OB += " ";662 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))663 OB += "(";664 OB += "*";665 } else {666 const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);667 OB += "id<";668 OB += objcProto->getProtocol();669 OB += ">";670 }671 }672 673 void printRight(OutputBuffer &OB) const override {674 if (Pointee->getKind() != KObjCProtoName ||675 !static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {676 if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))677 OB += ")";678 OB.printRight(*Pointee);679 }680 }681};682 683enum class ReferenceKind {684 LValue,685 RValue,686};687 688// Represents either a LValue or an RValue reference type.689class ReferenceType : public Node {690 const Node *Pointee;691 ReferenceKind RK;692 693 mutable bool Printing = false;694 695 // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The696 // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any697 // other combination collapses to a lvalue ref.698 //699 // A combination of a TemplateForwardReference and a back-ref Substitution700 // from an ill-formed string may have created a cycle; use cycle detection to701 // avoid looping forever.702 std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {703 auto SoFar = std::make_pair(RK, Pointee);704 // Track the chain of nodes for the Floyd's 'tortoise and hare'705 // cycle-detection algorithm, since getSyntaxNode(S) is impure706 PODSmallVector<const Node *, 8> Prev;707 for (;;) {708 const Node *SN = SoFar.second->getSyntaxNode(OB);709 if (SN->getKind() != KReferenceType)710 break;711 auto *RT = static_cast<const ReferenceType *>(SN);712 SoFar.second = RT->Pointee;713 SoFar.first = std::min(SoFar.first, RT->RK);714 715 // The middle of Prev is the 'slow' pointer moving at half speed716 Prev.push_back(SoFar.second);717 if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {718 // Cycle detected719 SoFar.second = nullptr;720 break;721 }722 }723 return SoFar;724 }725 726public:727 ReferenceType(const Node *Pointee_, ReferenceKind RK_)728 : Node(KReferenceType, Pointee_->getRHSComponentCache()),729 Pointee(Pointee_), RK(RK_) {}730 731 template<typename Fn> void match(Fn F) const { F(Pointee, RK); }732 733 bool hasRHSComponentSlow(OutputBuffer &OB) const override {734 return Pointee->hasRHSComponent(OB);735 }736 737 void printLeft(OutputBuffer &OB) const override {738 if (Printing)739 return;740 ScopedOverride<bool> SavePrinting(Printing, true);741 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);742 if (!Collapsed.second)743 return;744 OB.printLeft(*Collapsed.second);745 if (Collapsed.second->hasArray(OB))746 OB += " ";747 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))748 OB += "(";749 750 OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");751 }752 void printRight(OutputBuffer &OB) const override {753 if (Printing)754 return;755 ScopedOverride<bool> SavePrinting(Printing, true);756 std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);757 if (!Collapsed.second)758 return;759 if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))760 OB += ")";761 OB.printRight(*Collapsed.second);762 }763};764 765class PointerToMemberType final : public Node {766 const Node *ClassType;767 const Node *MemberType;768 769public:770 PointerToMemberType(const Node *ClassType_, const Node *MemberType_)771 : Node(KPointerToMemberType, MemberType_->getRHSComponentCache()),772 ClassType(ClassType_), MemberType(MemberType_) {}773 774 template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }775 776 bool hasRHSComponentSlow(OutputBuffer &OB) const override {777 return MemberType->hasRHSComponent(OB);778 }779 780 void printLeft(OutputBuffer &OB) const override {781 OB.printLeft(*MemberType);782 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))783 OB += "(";784 else785 OB += " ";786 ClassType->print(OB);787 OB += "::*";788 }789 790 void printRight(OutputBuffer &OB) const override {791 if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))792 OB += ")";793 OB.printRight(*MemberType);794 }795};796 797class ArrayType final : public Node {798 const Node *Base;799 Node *Dimension;800 801public:802 ArrayType(const Node *Base_, Node *Dimension_)803 : Node(KArrayType,804 /*RHSComponentCache=*/Cache::Yes,805 /*ArrayCache=*/Cache::Yes),806 Base(Base_), Dimension(Dimension_) {}807 808 template<typename Fn> void match(Fn F) const { F(Base, Dimension); }809 810 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }811 bool hasArraySlow(OutputBuffer &) const override { return true; }812 813 void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); }814 815 void printRight(OutputBuffer &OB) const override {816 if (OB.back() != ']')817 OB += " ";818 OB += "[";819 if (Dimension)820 Dimension->print(OB);821 OB += "]";822 OB.printRight(*Base);823 }824 825 bool printInitListAsType(OutputBuffer &OB,826 const NodeArray &Elements) const override {827 if (Base->getKind() == KNameType &&828 static_cast<const NameType *>(Base)->getName() == "char") {829 return Elements.printAsString(OB);830 }831 return false;832 }833};834 835class FunctionType final : public Node {836 const Node *Ret;837 NodeArray Params;838 Qualifiers CVQuals;839 FunctionRefQual RefQual;840 const Node *ExceptionSpec;841 842public:843 FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,844 FunctionRefQual RefQual_, const Node *ExceptionSpec_)845 : Node(KFunctionType,846 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,847 /*FunctionCache=*/Cache::Yes),848 Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),849 ExceptionSpec(ExceptionSpec_) {}850 851 template<typename Fn> void match(Fn F) const {852 F(Ret, Params, CVQuals, RefQual, ExceptionSpec);853 }854 855 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }856 bool hasFunctionSlow(OutputBuffer &) const override { return true; }857 858 // Handle C++'s ... quirky decl grammar by using the left & right859 // distinction. Consider:860 // int (*f(float))(char) {}861 // f is a function that takes a float and returns a pointer to a function862 // that takes a char and returns an int. If we're trying to print f, start863 // by printing out the return types's left, then print our parameters, then864 // finally print right of the return type.865 void printLeft(OutputBuffer &OB) const override {866 OB.printLeft(*Ret);867 OB += " ";868 }869 870 void printRight(OutputBuffer &OB) const override {871 OB.printOpen();872 Params.printWithComma(OB);873 OB.printClose();874 OB.printRight(*Ret);875 876 if (CVQuals & QualConst)877 OB += " const";878 if (CVQuals & QualVolatile)879 OB += " volatile";880 if (CVQuals & QualRestrict)881 OB += " restrict";882 883 if (RefQual == FrefQualLValue)884 OB += " &";885 else if (RefQual == FrefQualRValue)886 OB += " &&";887 888 if (ExceptionSpec != nullptr) {889 OB += ' ';890 ExceptionSpec->print(OB);891 }892 }893};894 895class NoexceptSpec : public Node {896 const Node *E;897public:898 NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}899 900 template<typename Fn> void match(Fn F) const { F(E); }901 902 void printLeft(OutputBuffer &OB) const override {903 OB += "noexcept";904 OB.printOpen();905 E->printAsOperand(OB);906 OB.printClose();907 }908};909 910class DynamicExceptionSpec : public Node {911 NodeArray Types;912public:913 DynamicExceptionSpec(NodeArray Types_)914 : Node(KDynamicExceptionSpec), Types(Types_) {}915 916 template<typename Fn> void match(Fn F) const { F(Types); }917 918 void printLeft(OutputBuffer &OB) const override {919 OB += "throw";920 OB.printOpen();921 Types.printWithComma(OB);922 OB.printClose();923 }924};925 926/// Represents the explicitly named object parameter.927/// E.g.,928/// \code{.cpp}929/// struct Foo {930/// void bar(this Foo && self);931/// };932/// \endcode933class ExplicitObjectParameter final : public Node {934 Node *Base;935 936public:937 ExplicitObjectParameter(Node *Base_)938 : Node(KExplicitObjectParameter), Base(Base_) {939 DEMANGLE_ASSERT(940 Base != nullptr,941 "Creating an ExplicitObjectParameter without a valid Base Node.");942 }943 944 template <typename Fn> void match(Fn F) const { F(Base); }945 946 void printLeft(OutputBuffer &OB) const override {947 OB += "this ";948 Base->print(OB);949 }950};951 952class FunctionEncoding final : public Node {953 const Node *Ret;954 const Node *Name;955 NodeArray Params;956 const Node *Attrs;957 const Node *Requires;958 Qualifiers CVQuals;959 FunctionRefQual RefQual;960 961public:962 FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,963 const Node *Attrs_, const Node *Requires_,964 Qualifiers CVQuals_, FunctionRefQual RefQual_)965 : Node(KFunctionEncoding,966 /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,967 /*FunctionCache=*/Cache::Yes),968 Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),969 Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}970 971 template<typename Fn> void match(Fn F) const {972 F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);973 }974 975 Qualifiers getCVQuals() const { return CVQuals; }976 FunctionRefQual getRefQual() const { return RefQual; }977 NodeArray getParams() const { return Params; }978 const Node *getReturnType() const { return Ret; }979 const Node *getAttrs() const { return Attrs; }980 const Node *getRequires() const { return Requires; }981 982 bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }983 bool hasFunctionSlow(OutputBuffer &) const override { return true; }984 985 const Node *getName() const { return Name; }986 987 void printLeft(OutputBuffer &OB) const override {988 if (Ret) {989 OB.printLeft(*Ret);990 if (!Ret->hasRHSComponent(OB))991 OB += " ";992 }993 994 Name->print(OB);995 }996 997 void printRight(OutputBuffer &OB) const override {998 OB.printOpen();999 Params.printWithComma(OB);1000 OB.printClose();1001 1002 if (Ret)1003 OB.printRight(*Ret);1004 1005 if (CVQuals & QualConst)1006 OB += " const";1007 if (CVQuals & QualVolatile)1008 OB += " volatile";1009 if (CVQuals & QualRestrict)1010 OB += " restrict";1011 1012 if (RefQual == FrefQualLValue)1013 OB += " &";1014 else if (RefQual == FrefQualRValue)1015 OB += " &&";1016 1017 if (Attrs != nullptr)1018 Attrs->print(OB);1019 1020 if (Requires != nullptr) {1021 OB += " requires ";1022 Requires->print(OB);1023 }1024 }1025};1026 1027class LiteralOperator : public Node {1028 const Node *OpName;1029 1030public:1031 LiteralOperator(const Node *OpName_)1032 : Node(KLiteralOperator), OpName(OpName_) {}1033 1034 template<typename Fn> void match(Fn F) const { F(OpName); }1035 1036 void printLeft(OutputBuffer &OB) const override {1037 OB += "operator\"\" ";1038 OpName->print(OB);1039 }1040};1041 1042class SpecialName final : public Node {1043 const std::string_view Special;1044 const Node *Child;1045 1046public:1047 SpecialName(std::string_view Special_, const Node *Child_)1048 : Node(KSpecialName), Special(Special_), Child(Child_) {}1049 1050 template<typename Fn> void match(Fn F) const { F(Special, Child); }1051 1052 void printLeft(OutputBuffer &OB) const override {1053 OB += Special;1054 Child->print(OB);1055 }1056};1057 1058class CtorVtableSpecialName final : public Node {1059 const Node *FirstType;1060 const Node *SecondType;1061 1062public:1063 CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)1064 : Node(KCtorVtableSpecialName),1065 FirstType(FirstType_), SecondType(SecondType_) {}1066 1067 template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }1068 1069 void printLeft(OutputBuffer &OB) const override {1070 OB += "construction vtable for ";1071 FirstType->print(OB);1072 OB += "-in-";1073 SecondType->print(OB);1074 }1075};1076 1077struct NestedName : Node {1078 Node *Qual;1079 Node *Name;1080 1081 NestedName(Node *Qual_, Node *Name_)1082 : Node(KNestedName), Qual(Qual_), Name(Name_) {}1083 1084 template<typename Fn> void match(Fn F) const { F(Qual, Name); }1085 1086 std::string_view getBaseName() const override { return Name->getBaseName(); }1087 1088 void printLeft(OutputBuffer &OB) const override {1089 Qual->print(OB);1090 OB += "::";1091 Name->print(OB);1092 }1093};1094 1095struct MemberLikeFriendName : Node {1096 Node *Qual;1097 Node *Name;1098 1099 MemberLikeFriendName(Node *Qual_, Node *Name_)1100 : Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}1101 1102 template<typename Fn> void match(Fn F) const { F(Qual, Name); }1103 1104 std::string_view getBaseName() const override { return Name->getBaseName(); }1105 1106 void printLeft(OutputBuffer &OB) const override {1107 Qual->print(OB);1108 OB += "::friend ";1109 Name->print(OB);1110 }1111};1112 1113struct ModuleName : Node {1114 ModuleName *Parent;1115 Node *Name;1116 bool IsPartition;1117 1118 ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)1119 : Node(KModuleName), Parent(Parent_), Name(Name_),1120 IsPartition(IsPartition_) {}1121 1122 template <typename Fn> void match(Fn F) const {1123 F(Parent, Name, IsPartition);1124 }1125 1126 void printLeft(OutputBuffer &OB) const override {1127 if (Parent)1128 Parent->print(OB);1129 if (Parent || IsPartition)1130 OB += IsPartition ? ':' : '.';1131 Name->print(OB);1132 }1133};1134 1135struct ModuleEntity : Node {1136 ModuleName *Module;1137 Node *Name;1138 1139 ModuleEntity(ModuleName *Module_, Node *Name_)1140 : Node(KModuleEntity), Module(Module_), Name(Name_) {}1141 1142 template <typename Fn> void match(Fn F) const { F(Module, Name); }1143 1144 std::string_view getBaseName() const override { return Name->getBaseName(); }1145 1146 void printLeft(OutputBuffer &OB) const override {1147 Name->print(OB);1148 OB += '@';1149 Module->print(OB);1150 }1151};1152 1153struct LocalName : Node {1154 Node *Encoding;1155 Node *Entity;1156 1157 LocalName(Node *Encoding_, Node *Entity_)1158 : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}1159 1160 template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }1161 1162 void printLeft(OutputBuffer &OB) const override {1163 Encoding->print(OB);1164 OB += "::";1165 Entity->print(OB);1166 }1167};1168 1169class QualifiedName final : public Node {1170 // qualifier::name1171 const Node *Qualifier;1172 const Node *Name;1173 1174public:1175 QualifiedName(const Node *Qualifier_, const Node *Name_)1176 : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}1177 1178 template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }1179 1180 std::string_view getBaseName() const override { return Name->getBaseName(); }1181 1182 void printLeft(OutputBuffer &OB) const override {1183 Qualifier->print(OB);1184 OB += "::";1185 Name->print(OB);1186 }1187};1188 1189class VectorType final : public Node {1190 const Node *BaseType;1191 const Node *Dimension;1192 1193public:1194 VectorType(const Node *BaseType_, const Node *Dimension_)1195 : Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}1196 1197 const Node *getBaseType() const { return BaseType; }1198 const Node *getDimension() const { return Dimension; }1199 1200 template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }1201 1202 void printLeft(OutputBuffer &OB) const override {1203 BaseType->print(OB);1204 OB += " vector[";1205 if (Dimension)1206 Dimension->print(OB);1207 OB += "]";1208 }1209};1210 1211class PixelVectorType final : public Node {1212 const Node *Dimension;1213 1214public:1215 PixelVectorType(const Node *Dimension_)1216 : Node(KPixelVectorType), Dimension(Dimension_) {}1217 1218 template<typename Fn> void match(Fn F) const { F(Dimension); }1219 1220 void printLeft(OutputBuffer &OB) const override {1221 // FIXME: This should demangle as "vector pixel".1222 OB += "pixel vector[";1223 Dimension->print(OB);1224 OB += "]";1225 }1226};1227 1228class BinaryFPType final : public Node {1229 const Node *Dimension;1230 1231public:1232 BinaryFPType(const Node *Dimension_)1233 : Node(KBinaryFPType), Dimension(Dimension_) {}1234 1235 template<typename Fn> void match(Fn F) const { F(Dimension); }1236 1237 void printLeft(OutputBuffer &OB) const override {1238 OB += "_Float";1239 Dimension->print(OB);1240 }1241};1242 1243enum class TemplateParamKind { Type, NonType, Template };1244 1245/// An invented name for a template parameter for which we don't have a1246/// corresponding template argument.1247///1248/// This node is created when parsing the <lambda-sig> for a lambda with1249/// explicit template arguments, which might be referenced in the parameter1250/// types appearing later in the <lambda-sig>.1251class SyntheticTemplateParamName final : public Node {1252 TemplateParamKind Kind;1253 unsigned Index;1254 1255public:1256 SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)1257 : Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}1258 1259 template<typename Fn> void match(Fn F) const { F(Kind, Index); }1260 1261 void printLeft(OutputBuffer &OB) const override {1262 switch (Kind) {1263 case TemplateParamKind::Type:1264 OB += "$T";1265 break;1266 case TemplateParamKind::NonType:1267 OB += "$N";1268 break;1269 case TemplateParamKind::Template:1270 OB += "$TT";1271 break;1272 }1273 if (Index > 0)1274 OB << Index - 1;1275 }1276};1277 1278class TemplateParamQualifiedArg final : public Node {1279 Node *Param;1280 Node *Arg;1281 1282public:1283 TemplateParamQualifiedArg(Node *Param_, Node *Arg_)1284 : Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}1285 1286 template <typename Fn> void match(Fn F) const { F(Param, Arg); }1287 1288 Node *getArg() { return Arg; }1289 1290 void printLeft(OutputBuffer &OB) const override {1291 // Don't print Param to keep the output consistent.1292 Arg->print(OB);1293 }1294};1295 1296/// A template type parameter declaration, 'typename T'.1297class TypeTemplateParamDecl final : public Node {1298 Node *Name;1299 1300public:1301 TypeTemplateParamDecl(Node *Name_)1302 : Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}1303 1304 template<typename Fn> void match(Fn F) const { F(Name); }1305 1306 void printLeft(OutputBuffer &OB) const override { OB += "typename "; }1307 1308 void printRight(OutputBuffer &OB) const override { Name->print(OB); }1309};1310 1311/// A constrained template type parameter declaration, 'C<U> T'.1312class ConstrainedTypeTemplateParamDecl final : public Node {1313 Node *Constraint;1314 Node *Name;1315 1316public:1317 ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)1318 : Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),1319 Constraint(Constraint_), Name(Name_) {}1320 1321 template<typename Fn> void match(Fn F) const { F(Constraint, Name); }1322 1323 void printLeft(OutputBuffer &OB) const override {1324 Constraint->print(OB);1325 OB += " ";1326 }1327 1328 void printRight(OutputBuffer &OB) const override { Name->print(OB); }1329};1330 1331/// A non-type template parameter declaration, 'int N'.1332class NonTypeTemplateParamDecl final : public Node {1333 Node *Name;1334 Node *Type;1335 1336public:1337 NonTypeTemplateParamDecl(Node *Name_, Node *Type_)1338 : Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}1339 1340 template<typename Fn> void match(Fn F) const { F(Name, Type); }1341 1342 void printLeft(OutputBuffer &OB) const override {1343 OB.printLeft(*Type);1344 if (!Type->hasRHSComponent(OB))1345 OB += " ";1346 }1347 1348 void printRight(OutputBuffer &OB) const override {1349 Name->print(OB);1350 OB.printRight(*Type);1351 }1352};1353 1354/// A template template parameter declaration,1355/// 'template<typename T> typename N'.1356class TemplateTemplateParamDecl final : public Node {1357 Node *Name;1358 NodeArray Params;1359 Node *Requires;1360 1361public:1362 TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)1363 : Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),1364 Params(Params_), Requires(Requires_) {}1365 1366 template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }1367 1368 void printLeft(OutputBuffer &OB) const override {1369 ScopedOverride<bool> LT(OB.TemplateTracker.InsideTemplate, true);1370 OB += "template<";1371 Params.printWithComma(OB);1372 OB += "> typename ";1373 }1374 1375 void printRight(OutputBuffer &OB) const override {1376 Name->print(OB);1377 if (Requires != nullptr) {1378 OB += " requires ";1379 Requires->print(OB);1380 }1381 }1382};1383 1384/// A template parameter pack declaration, 'typename ...T'.1385class TemplateParamPackDecl final : public Node {1386 Node *Param;1387 1388public:1389 TemplateParamPackDecl(Node *Param_)1390 : Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}1391 1392 template<typename Fn> void match(Fn F) const { F(Param); }1393 1394 void printLeft(OutputBuffer &OB) const override {1395 OB.printLeft(*Param);1396 OB += "...";1397 }1398 1399 void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); }1400};1401 1402/// An unexpanded parameter pack (either in the expression or type context). If1403/// this AST is correct, this node will have a ParameterPackExpansion node above1404/// it.1405///1406/// This node is created when some <template-args> are found that apply to an1407/// <encoding>, and is stored in the TemplateParams table. In order for this to1408/// appear in the final AST, it has to referenced via a <template-param> (ie,1409/// T_).1410class ParameterPack final : public Node {1411 NodeArray Data;1412 1413 // Setup OutputBuffer for a pack expansion, unless we're already expanding1414 // one.1415 void initializePackExpansion(OutputBuffer &OB) const {1416 if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {1417 OB.CurrentPackMax = static_cast<unsigned>(Data.size());1418 OB.CurrentPackIndex = 0;1419 }1420 }1421 1422public:1423 ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {1424 ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;1425 if (std::all_of(Data.begin(), Data.end(),1426 [](Node *P) { return P->getArrayCache() == Cache::No; }))1427 ArrayCache = Cache::No;1428 if (std::all_of(Data.begin(), Data.end(),1429 [](Node *P) { return P->getFunctionCache() == Cache::No; }))1430 FunctionCache = Cache::No;1431 if (std::all_of(Data.begin(), Data.end(), [](Node *P) {1432 return P->getRHSComponentCache() == Cache::No;1433 }))1434 RHSComponentCache = Cache::No;1435 }1436 1437 template<typename Fn> void match(Fn F) const { F(Data); }1438 1439 bool hasRHSComponentSlow(OutputBuffer &OB) const override {1440 initializePackExpansion(OB);1441 size_t Idx = OB.CurrentPackIndex;1442 return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);1443 }1444 bool hasArraySlow(OutputBuffer &OB) const override {1445 initializePackExpansion(OB);1446 size_t Idx = OB.CurrentPackIndex;1447 return Idx < Data.size() && Data[Idx]->hasArray(OB);1448 }1449 bool hasFunctionSlow(OutputBuffer &OB) const override {1450 initializePackExpansion(OB);1451 size_t Idx = OB.CurrentPackIndex;1452 return Idx < Data.size() && Data[Idx]->hasFunction(OB);1453 }1454 const Node *getSyntaxNode(OutputBuffer &OB) const override {1455 initializePackExpansion(OB);1456 size_t Idx = OB.CurrentPackIndex;1457 return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;1458 }1459 1460 void printLeft(OutputBuffer &OB) const override {1461 initializePackExpansion(OB);1462 size_t Idx = OB.CurrentPackIndex;1463 if (Idx < Data.size())1464 OB.printLeft(*Data[Idx]);1465 }1466 void printRight(OutputBuffer &OB) const override {1467 initializePackExpansion(OB);1468 size_t Idx = OB.CurrentPackIndex;1469 if (Idx < Data.size())1470 OB.printRight(*Data[Idx]);1471 }1472};1473 1474/// A variadic template argument. This node represents an occurrence of1475/// J<something>E in some <template-args>. It isn't itself unexpanded, unless1476/// one of its Elements is. The parser inserts a ParameterPack into the1477/// TemplateParams table if the <template-args> this pack belongs to apply to an1478/// <encoding>.1479class TemplateArgumentPack final : public Node {1480 NodeArray Elements;1481public:1482 TemplateArgumentPack(NodeArray Elements_)1483 : Node(KTemplateArgumentPack), Elements(Elements_) {}1484 1485 template<typename Fn> void match(Fn F) const { F(Elements); }1486 1487 NodeArray getElements() const { return Elements; }1488 1489 void printLeft(OutputBuffer &OB) const override {1490 Elements.printWithComma(OB);1491 }1492};1493 1494/// A pack expansion. Below this node, there are some unexpanded ParameterPacks1495/// which each have Child->ParameterPackSize elements.1496class ParameterPackExpansion final : public Node {1497 const Node *Child;1498 1499public:1500 ParameterPackExpansion(const Node *Child_)1501 : Node(KParameterPackExpansion), Child(Child_) {}1502 1503 template<typename Fn> void match(Fn F) const { F(Child); }1504 1505 const Node *getChild() const { return Child; }1506 1507 void printLeft(OutputBuffer &OB) const override {1508 constexpr unsigned Max = std::numeric_limits<unsigned>::max();1509 ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);1510 ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);1511 size_t StreamPos = OB.getCurrentPosition();1512 1513 // Print the first element in the pack. If Child contains a ParameterPack,1514 // it will set up S.CurrentPackMax and print the first element.1515 Child->print(OB);1516 1517 // No ParameterPack was found in Child. This can occur if we've found a pack1518 // expansion on a <function-param>.1519 if (OB.CurrentPackMax == Max) {1520 OB += "...";1521 return;1522 }1523 1524 // We found a ParameterPack, but it has no elements. Erase whatever we may1525 // of printed.1526 if (OB.CurrentPackMax == 0) {1527 OB.setCurrentPosition(StreamPos);1528 return;1529 }1530 1531 // Else, iterate through the rest of the elements in the pack.1532 for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {1533 OB += ", ";1534 OB.CurrentPackIndex = I;1535 Child->print(OB);1536 }1537 }1538};1539 1540class TemplateArgs final : public Node {1541 NodeArray Params;1542 Node *Requires;1543 1544public:1545 TemplateArgs(NodeArray Params_, Node *Requires_)1546 : Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}1547 1548 template<typename Fn> void match(Fn F) const { F(Params, Requires); }1549 1550 NodeArray getParams() { return Params; }1551 1552 void printLeft(OutputBuffer &OB) const override {1553 ScopedOverride<bool> LT(OB.TemplateTracker.InsideTemplate, true);1554 OB += "<";1555 Params.printWithComma(OB);1556 OB += ">";1557 // Don't print the requires clause to keep the output simple.1558 }1559};1560 1561/// A forward-reference to a template argument that was not known at the point1562/// where the template parameter name was parsed in a mangling.1563///1564/// This is created when demangling the name of a specialization of a1565/// conversion function template:1566///1567/// \code1568/// struct A {1569/// template<typename T> operator T*();1570/// };1571/// \endcode1572///1573/// When demangling a specialization of the conversion function template, we1574/// encounter the name of the template (including the \c T) before we reach1575/// the template argument list, so we cannot substitute the parameter name1576/// for the corresponding argument while parsing. Instead, we create a1577/// \c ForwardTemplateReference node that is resolved after we parse the1578/// template arguments.1579struct ForwardTemplateReference : Node {1580 size_t Index;1581 Node *Ref = nullptr;1582 1583 // If we're currently printing this node. It is possible (though invalid) for1584 // a forward template reference to refer to itself via a substitution. This1585 // creates a cyclic AST, which will stack overflow printing. To fix this, bail1586 // out if more than one print* function is active.1587 mutable bool Printing = false;1588 1589 ForwardTemplateReference(size_t Index_)1590 : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,1591 Cache::Unknown),1592 Index(Index_) {}1593 1594 // We don't provide a matcher for these, because the value of the node is1595 // not determined by its construction parameters, and it generally needs1596 // special handling.1597 template<typename Fn> void match(Fn F) const = delete;1598 1599 bool hasRHSComponentSlow(OutputBuffer &OB) const override {1600 if (Printing)1601 return false;1602 ScopedOverride<bool> SavePrinting(Printing, true);1603 return Ref->hasRHSComponent(OB);1604 }1605 bool hasArraySlow(OutputBuffer &OB) const override {1606 if (Printing)1607 return false;1608 ScopedOverride<bool> SavePrinting(Printing, true);1609 return Ref->hasArray(OB);1610 }1611 bool hasFunctionSlow(OutputBuffer &OB) const override {1612 if (Printing)1613 return false;1614 ScopedOverride<bool> SavePrinting(Printing, true);1615 return Ref->hasFunction(OB);1616 }1617 const Node *getSyntaxNode(OutputBuffer &OB) const override {1618 if (Printing)1619 return this;1620 ScopedOverride<bool> SavePrinting(Printing, true);1621 return Ref->getSyntaxNode(OB);1622 }1623 1624 void printLeft(OutputBuffer &OB) const override {1625 if (Printing)1626 return;1627 ScopedOverride<bool> SavePrinting(Printing, true);1628 OB.printLeft(*Ref);1629 }1630 void printRight(OutputBuffer &OB) const override {1631 if (Printing)1632 return;1633 ScopedOverride<bool> SavePrinting(Printing, true);1634 OB.printRight(*Ref);1635 }1636};1637 1638struct NameWithTemplateArgs : Node {1639 // name<template_args>1640 Node *Name;1641 Node *TemplateArgs;1642 1643 NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)1644 : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}1645 1646 template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }1647 1648 std::string_view getBaseName() const override { return Name->getBaseName(); }1649 1650 void printLeft(OutputBuffer &OB) const override {1651 Name->print(OB);1652 TemplateArgs->print(OB);1653 }1654};1655 1656class GlobalQualifiedName final : public Node {1657 Node *Child;1658 1659public:1660 GlobalQualifiedName(Node* Child_)1661 : Node(KGlobalQualifiedName), Child(Child_) {}1662 1663 template<typename Fn> void match(Fn F) const { F(Child); }1664 1665 std::string_view getBaseName() const override { return Child->getBaseName(); }1666 1667 void printLeft(OutputBuffer &OB) const override {1668 OB += "::";1669 Child->print(OB);1670 }1671};1672 1673enum class SpecialSubKind {1674 allocator,1675 basic_string,1676 string,1677 istream,1678 ostream,1679 iostream,1680};1681 1682class SpecialSubstitution;1683class ExpandedSpecialSubstitution : public Node {1684protected:1685 SpecialSubKind SSK;1686 1687 ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)1688 : Node(K_), SSK(SSK_) {}1689public:1690 ExpandedSpecialSubstitution(SpecialSubKind SSK_)1691 : ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}1692 inline ExpandedSpecialSubstitution(SpecialSubstitution const *);1693 1694 template<typename Fn> void match(Fn F) const { F(SSK); }1695 1696protected:1697 bool isInstantiation() const {1698 return unsigned(SSK) >= unsigned(SpecialSubKind::string);1699 }1700 1701 std::string_view getBaseName() const override {1702 switch (SSK) {1703 case SpecialSubKind::allocator:1704 return {"allocator"};1705 case SpecialSubKind::basic_string:1706 return {"basic_string"};1707 case SpecialSubKind::string:1708 return {"basic_string"};1709 case SpecialSubKind::istream:1710 return {"basic_istream"};1711 case SpecialSubKind::ostream:1712 return {"basic_ostream"};1713 case SpecialSubKind::iostream:1714 return {"basic_iostream"};1715 }1716 DEMANGLE_UNREACHABLE;1717 }1718 1719private:1720 void printLeft(OutputBuffer &OB) const override {1721 OB << "std::" << getBaseName();1722 if (isInstantiation()) {1723 OB << "<char, std::char_traits<char>";1724 if (SSK == SpecialSubKind::string)1725 OB << ", std::allocator<char>";1726 OB << ">";1727 }1728 }1729};1730 1731class SpecialSubstitution final : public ExpandedSpecialSubstitution {1732public:1733 SpecialSubstitution(SpecialSubKind SSK_)1734 : ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}1735 1736 template<typename Fn> void match(Fn F) const { F(SSK); }1737 1738 std::string_view getBaseName() const override {1739 std::string_view SV = ExpandedSpecialSubstitution::getBaseName();1740 if (isInstantiation()) {1741 // The instantiations are typedefs that drop the "basic_" prefix.1742 DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");1743 SV.remove_prefix(sizeof("basic_") - 1);1744 }1745 return SV;1746 }1747 1748 void printLeft(OutputBuffer &OB) const override {1749 OB << "std::" << getBaseName();1750 }1751};1752 1753inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(1754 SpecialSubstitution const *SS)1755 : ExpandedSpecialSubstitution(SS->SSK) {}1756 1757class CtorDtorName final : public Node {1758 const Node *Basename;1759 const bool IsDtor;1760 const int Variant;1761 1762public:1763 CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)1764 : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),1765 Variant(Variant_) {}1766 1767 template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }1768 1769 void printLeft(OutputBuffer &OB) const override {1770 if (IsDtor)1771 OB += "~";1772 OB += Basename->getBaseName();1773 }1774};1775 1776class DtorName : public Node {1777 const Node *Base;1778 1779public:1780 DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}1781 1782 template<typename Fn> void match(Fn F) const { F(Base); }1783 1784 void printLeft(OutputBuffer &OB) const override {1785 OB += "~";1786 OB.printLeft(*Base);1787 }1788};1789 1790class UnnamedTypeName : public Node {1791 const std::string_view Count;1792 1793public:1794 UnnamedTypeName(std::string_view Count_)1795 : Node(KUnnamedTypeName), Count(Count_) {}1796 1797 template<typename Fn> void match(Fn F) const { F(Count); }1798 1799 void printLeft(OutputBuffer &OB) const override {1800 OB += "'unnamed";1801 OB += Count;1802 OB += "\'";1803 }1804};1805 1806class ClosureTypeName : public Node {1807 NodeArray TemplateParams;1808 const Node *Requires1;1809 NodeArray Params;1810 const Node *Requires2;1811 std::string_view Count;1812 1813public:1814 ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,1815 NodeArray Params_, const Node *Requires2_,1816 std::string_view Count_)1817 : Node(KClosureTypeName), TemplateParams(TemplateParams_),1818 Requires1(Requires1_), Params(Params_), Requires2(Requires2_),1819 Count(Count_) {}1820 1821 template<typename Fn> void match(Fn F) const {1822 F(TemplateParams, Requires1, Params, Requires2, Count);1823 }1824 1825 void printDeclarator(OutputBuffer &OB) const {1826 if (!TemplateParams.empty()) {1827 ScopedOverride<bool> LT(OB.TemplateTracker.InsideTemplate, true);1828 OB += "<";1829 TemplateParams.printWithComma(OB);1830 OB += ">";1831 }1832 if (Requires1 != nullptr) {1833 OB += " requires ";1834 Requires1->print(OB);1835 OB += " ";1836 }1837 OB.printOpen();1838 Params.printWithComma(OB);1839 OB.printClose();1840 if (Requires2 != nullptr) {1841 OB += " requires ";1842 Requires2->print(OB);1843 }1844 }1845 1846 void printLeft(OutputBuffer &OB) const override {1847 // FIXME: This demangling is not particularly readable.1848 OB += "\'lambda";1849 OB += Count;1850 OB += "\'";1851 printDeclarator(OB);1852 }1853};1854 1855class StructuredBindingName : public Node {1856 NodeArray Bindings;1857public:1858 StructuredBindingName(NodeArray Bindings_)1859 : Node(KStructuredBindingName), Bindings(Bindings_) {}1860 1861 template<typename Fn> void match(Fn F) const { F(Bindings); }1862 1863 void printLeft(OutputBuffer &OB) const override {1864 OB.printOpen('[');1865 Bindings.printWithComma(OB);1866 OB.printClose(']');1867 }1868};1869 1870// -- Expression Nodes --1871 1872class BinaryExpr : public Node {1873 const Node *LHS;1874 const std::string_view InfixOperator;1875 const Node *RHS;1876 1877public:1878 BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,1879 const Node *RHS_, Prec Prec_)1880 : Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),1881 RHS(RHS_) {}1882 1883 template <typename Fn> void match(Fn F) const {1884 F(LHS, InfixOperator, RHS, getPrecedence());1885 }1886 1887 void printLeft(OutputBuffer &OB) const override {1888 // If we're printing a '<' inside of a template argument, and we haven't1889 // yet parenthesized the expression, do so now.1890 bool ParenAll = !OB.isInParensInTemplateArgs() &&1891 (InfixOperator == ">" || InfixOperator == ">>");1892 if (ParenAll)1893 OB.printOpen();1894 // Assignment is right associative, with special LHS precedence.1895 bool IsAssign = getPrecedence() == Prec::Assign;1896 LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);1897 // No space before comma operator1898 if (!(InfixOperator == ","))1899 OB += " ";1900 OB += InfixOperator;1901 OB += " ";1902 RHS->printAsOperand(OB, getPrecedence(), IsAssign);1903 if (ParenAll)1904 OB.printClose();1905 }1906};1907 1908class ArraySubscriptExpr : public Node {1909 const Node *Op1;1910 const Node *Op2;1911 1912public:1913 ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)1914 : Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}1915 1916 template <typename Fn> void match(Fn F) const {1917 F(Op1, Op2, getPrecedence());1918 }1919 1920 void printLeft(OutputBuffer &OB) const override {1921 Op1->printAsOperand(OB, getPrecedence());1922 OB.printOpen('[');1923 Op2->printAsOperand(OB);1924 OB.printClose(']');1925 }1926};1927 1928class PostfixExpr : public Node {1929 const Node *Child;1930 const std::string_view Operator;1931 1932public:1933 PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)1934 : Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}1935 1936 template <typename Fn> void match(Fn F) const {1937 F(Child, Operator, getPrecedence());1938 }1939 1940 void printLeft(OutputBuffer &OB) const override {1941 Child->printAsOperand(OB, getPrecedence(), true);1942 OB += Operator;1943 }1944};1945 1946class ConditionalExpr : public Node {1947 const Node *Cond;1948 const Node *Then;1949 const Node *Else;1950 1951public:1952 ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,1953 Prec Prec_)1954 : Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}1955 1956 template <typename Fn> void match(Fn F) const {1957 F(Cond, Then, Else, getPrecedence());1958 }1959 1960 void printLeft(OutputBuffer &OB) const override {1961 Cond->printAsOperand(OB, getPrecedence());1962 OB += " ? ";1963 Then->printAsOperand(OB);1964 OB += " : ";1965 Else->printAsOperand(OB, Prec::Assign, true);1966 }1967};1968 1969class MemberExpr : public Node {1970 const Node *LHS;1971 const std::string_view Kind;1972 const Node *RHS;1973 1974public:1975 MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,1976 Prec Prec_)1977 : Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}1978 1979 template <typename Fn> void match(Fn F) const {1980 F(LHS, Kind, RHS, getPrecedence());1981 }1982 1983 void printLeft(OutputBuffer &OB) const override {1984 LHS->printAsOperand(OB, getPrecedence(), true);1985 OB += Kind;1986 RHS->printAsOperand(OB, getPrecedence(), false);1987 }1988};1989 1990class SubobjectExpr : public Node {1991 const Node *Type;1992 const Node *SubExpr;1993 std::string_view Offset;1994 NodeArray UnionSelectors;1995 bool OnePastTheEnd;1996 1997public:1998 SubobjectExpr(const Node *Type_, const Node *SubExpr_,1999 std::string_view Offset_, NodeArray UnionSelectors_,2000 bool OnePastTheEnd_)2001 : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),2002 UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}2003 2004 template<typename Fn> void match(Fn F) const {2005 F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);2006 }2007 2008 void printLeft(OutputBuffer &OB) const override {2009 SubExpr->print(OB);2010 OB += ".<";2011 Type->print(OB);2012 OB += " at offset ";2013 if (Offset.empty()) {2014 OB += "0";2015 } else if (Offset[0] == 'n') {2016 OB += "-";2017 OB += std::string_view(Offset.data() + 1, Offset.size() - 1);2018 } else {2019 OB += Offset;2020 }2021 OB += ">";2022 }2023};2024 2025class EnclosingExpr : public Node {2026 const std::string_view Prefix;2027 const Node *Infix;2028 const std::string_view Postfix;2029 2030public:2031 EnclosingExpr(std::string_view Prefix_, const Node *Infix_,2032 Prec Prec_ = Prec::Primary)2033 : Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}2034 2035 template <typename Fn> void match(Fn F) const {2036 F(Prefix, Infix, getPrecedence());2037 }2038 2039 void printLeft(OutputBuffer &OB) const override {2040 OB += Prefix;2041 OB.printOpen();2042 Infix->print(OB);2043 OB.printClose();2044 OB += Postfix;2045 }2046};2047 2048class CastExpr : public Node {2049 // cast_kind<to>(from)2050 const std::string_view CastKind;2051 const Node *To;2052 const Node *From;2053 2054public:2055 CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,2056 Prec Prec_)2057 : Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}2058 2059 template <typename Fn> void match(Fn F) const {2060 F(CastKind, To, From, getPrecedence());2061 }2062 2063 void printLeft(OutputBuffer &OB) const override {2064 OB += CastKind;2065 {2066 ScopedOverride<bool> LT(OB.TemplateTracker.InsideTemplate, true);2067 OB += "<";2068 OB.printLeft(*To);2069 OB += ">";2070 }2071 OB.printOpen();2072 From->printAsOperand(OB);2073 OB.printClose();2074 }2075};2076 2077class SizeofParamPackExpr : public Node {2078 const Node *Pack;2079 2080public:2081 SizeofParamPackExpr(const Node *Pack_)2082 : Node(KSizeofParamPackExpr), Pack(Pack_) {}2083 2084 template<typename Fn> void match(Fn F) const { F(Pack); }2085 2086 void printLeft(OutputBuffer &OB) const override {2087 OB += "sizeof...";2088 OB.printOpen();2089 ParameterPackExpansion PPE(Pack);2090 PPE.printLeft(OB);2091 OB.printClose();2092 }2093};2094 2095class CallExpr : public Node {2096 const Node *Callee;2097 NodeArray Args;2098 bool IsParen; // (func)(args ...) ?2099 2100public:2101 CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_)2102 : Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_),2103 IsParen(IsParen_) {}2104 2105 template <typename Fn> void match(Fn F) const {2106 F(Callee, Args, IsParen, getPrecedence());2107 }2108 2109 void printLeft(OutputBuffer &OB) const override {2110 if (IsParen)2111 OB.printOpen();2112 Callee->print(OB);2113 if (IsParen)2114 OB.printClose();2115 OB.printOpen();2116 Args.printWithComma(OB);2117 OB.printClose();2118 }2119};2120 2121class NewExpr : public Node {2122 // new (expr_list) type(init_list)2123 NodeArray ExprList;2124 Node *Type;2125 NodeArray InitList;2126 bool IsGlobal; // ::operator new ?2127 bool IsArray; // new[] ?2128public:2129 NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,2130 bool IsArray_, Prec Prec_)2131 : Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),2132 InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}2133 2134 template<typename Fn> void match(Fn F) const {2135 F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());2136 }2137 2138 void printLeft(OutputBuffer &OB) const override {2139 if (IsGlobal)2140 OB += "::";2141 OB += "new";2142 if (IsArray)2143 OB += "[]";2144 if (!ExprList.empty()) {2145 OB.printOpen();2146 ExprList.printWithComma(OB);2147 OB.printClose();2148 }2149 OB += " ";2150 Type->print(OB);2151 if (!InitList.empty()) {2152 OB.printOpen();2153 InitList.printWithComma(OB);2154 OB.printClose();2155 }2156 }2157};2158 2159class DeleteExpr : public Node {2160 Node *Op;2161 bool IsGlobal;2162 bool IsArray;2163 2164public:2165 DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)2166 : Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),2167 IsArray(IsArray_) {}2168 2169 template <typename Fn> void match(Fn F) const {2170 F(Op, IsGlobal, IsArray, getPrecedence());2171 }2172 2173 void printLeft(OutputBuffer &OB) const override {2174 if (IsGlobal)2175 OB += "::";2176 OB += "delete";2177 if (IsArray)2178 OB += "[]";2179 OB += ' ';2180 Op->print(OB);2181 }2182};2183 2184class PrefixExpr : public Node {2185 std::string_view Prefix;2186 Node *Child;2187 2188public:2189 PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)2190 : Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}2191 2192 template <typename Fn> void match(Fn F) const {2193 F(Prefix, Child, getPrecedence());2194 }2195 2196 void printLeft(OutputBuffer &OB) const override {2197 OB += Prefix;2198 Child->printAsOperand(OB, getPrecedence());2199 }2200};2201 2202class FunctionParam : public Node {2203 std::string_view Number;2204 2205public:2206 FunctionParam(std::string_view Number_)2207 : Node(KFunctionParam), Number(Number_) {}2208 2209 template<typename Fn> void match(Fn F) const { F(Number); }2210 2211 void printLeft(OutputBuffer &OB) const override {2212 OB += "fp";2213 OB += Number;2214 }2215};2216 2217class ConversionExpr : public Node {2218 const Node *Type;2219 NodeArray Expressions;2220 2221public:2222 ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)2223 : Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}2224 2225 template <typename Fn> void match(Fn F) const {2226 F(Type, Expressions, getPrecedence());2227 }2228 2229 void printLeft(OutputBuffer &OB) const override {2230 OB.printOpen();2231 Type->print(OB);2232 OB.printClose();2233 OB.printOpen();2234 Expressions.printWithComma(OB);2235 OB.printClose();2236 }2237};2238 2239class PointerToMemberConversionExpr : public Node {2240 const Node *Type;2241 const Node *SubExpr;2242 std::string_view Offset;2243 2244public:2245 PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,2246 std::string_view Offset_, Prec Prec_)2247 : Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),2248 SubExpr(SubExpr_), Offset(Offset_) {}2249 2250 template <typename Fn> void match(Fn F) const {2251 F(Type, SubExpr, Offset, getPrecedence());2252 }2253 2254 void printLeft(OutputBuffer &OB) const override {2255 OB.printOpen();2256 Type->print(OB);2257 OB.printClose();2258 OB.printOpen();2259 SubExpr->print(OB);2260 OB.printClose();2261 }2262};2263 2264class InitListExpr : public Node {2265 const Node *Ty;2266 NodeArray Inits;2267public:2268 InitListExpr(const Node *Ty_, NodeArray Inits_)2269 : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}2270 2271 template<typename Fn> void match(Fn F) const { F(Ty, Inits); }2272 2273 void printLeft(OutputBuffer &OB) const override {2274 if (Ty) {2275 if (Ty->printInitListAsType(OB, Inits))2276 return;2277 Ty->print(OB);2278 }2279 OB += '{';2280 Inits.printWithComma(OB);2281 OB += '}';2282 }2283};2284 2285class BracedExpr : public Node {2286 const Node *Elem;2287 const Node *Init;2288 bool IsArray;2289public:2290 BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)2291 : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}2292 2293 template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }2294 2295 void printLeft(OutputBuffer &OB) const override {2296 if (IsArray) {2297 OB += '[';2298 Elem->print(OB);2299 OB += ']';2300 } else {2301 OB += '.';2302 Elem->print(OB);2303 }2304 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2305 OB += " = ";2306 Init->print(OB);2307 }2308};2309 2310class BracedRangeExpr : public Node {2311 const Node *First;2312 const Node *Last;2313 const Node *Init;2314public:2315 BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)2316 : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}2317 2318 template<typename Fn> void match(Fn F) const { F(First, Last, Init); }2319 2320 void printLeft(OutputBuffer &OB) const override {2321 OB += '[';2322 First->print(OB);2323 OB += " ... ";2324 Last->print(OB);2325 OB += ']';2326 if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2327 OB += " = ";2328 Init->print(OB);2329 }2330};2331 2332class FoldExpr : public Node {2333 const Node *Pack, *Init;2334 std::string_view OperatorName;2335 bool IsLeftFold;2336 2337public:2338 FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,2339 const Node *Init_)2340 : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),2341 IsLeftFold(IsLeftFold_) {}2342 2343 template<typename Fn> void match(Fn F) const {2344 F(IsLeftFold, OperatorName, Pack, Init);2345 }2346 2347 void printLeft(OutputBuffer &OB) const override {2348 auto PrintPack = [&] {2349 OB.printOpen();2350 ParameterPackExpansion(Pack).print(OB);2351 OB.printClose();2352 };2353 2354 OB.printOpen();2355 // Either '[init op ]... op pack' or 'pack op ...[ op init]'2356 // Refactored to '[(init|pack) op ]...[ op (pack|init)]'2357 // Fold expr operands are cast-expressions2358 if (!IsLeftFold || Init != nullptr) {2359 // '(init|pack) op '2360 if (IsLeftFold)2361 Init->printAsOperand(OB, Prec::Cast, true);2362 else2363 PrintPack();2364 OB << " " << OperatorName << " ";2365 }2366 OB << "...";2367 if (IsLeftFold || Init != nullptr) {2368 // ' op (init|pack)'2369 OB << " " << OperatorName << " ";2370 if (IsLeftFold)2371 PrintPack();2372 else2373 Init->printAsOperand(OB, Prec::Cast, true);2374 }2375 OB.printClose();2376 }2377};2378 2379class ThrowExpr : public Node {2380 const Node *Op;2381 2382public:2383 ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}2384 2385 template<typename Fn> void match(Fn F) const { F(Op); }2386 2387 void printLeft(OutputBuffer &OB) const override {2388 OB += "throw ";2389 Op->print(OB);2390 }2391};2392 2393class BoolExpr : public Node {2394 bool Value;2395 2396public:2397 BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}2398 2399 template<typename Fn> void match(Fn F) const { F(Value); }2400 2401 void printLeft(OutputBuffer &OB) const override {2402 OB += Value ? std::string_view("true") : std::string_view("false");2403 }2404};2405 2406class StringLiteral : public Node {2407 const Node *Type;2408 2409public:2410 StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}2411 2412 template<typename Fn> void match(Fn F) const { F(Type); }2413 2414 void printLeft(OutputBuffer &OB) const override {2415 OB += "\"<";2416 Type->print(OB);2417 OB += ">\"";2418 }2419};2420 2421class LambdaExpr : public Node {2422 const Node *Type;2423 2424public:2425 LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}2426 2427 template<typename Fn> void match(Fn F) const { F(Type); }2428 2429 void printLeft(OutputBuffer &OB) const override {2430 OB += "[]";2431 if (Type->getKind() == KClosureTypeName)2432 static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);2433 OB += "{...}";2434 }2435};2436 2437class EnumLiteral : public Node {2438 // ty(integer)2439 const Node *Ty;2440 std::string_view Integer;2441 2442public:2443 EnumLiteral(const Node *Ty_, std::string_view Integer_)2444 : Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}2445 2446 template<typename Fn> void match(Fn F) const { F(Ty, Integer); }2447 2448 void printLeft(OutputBuffer &OB) const override {2449 OB.printOpen();2450 Ty->print(OB);2451 OB.printClose();2452 2453 if (Integer[0] == 'n')2454 OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);2455 else2456 OB << Integer;2457 }2458};2459 2460class IntegerLiteral : public Node {2461 std::string_view Type;2462 std::string_view Value;2463 2464public:2465 IntegerLiteral(std::string_view Type_, std::string_view Value_)2466 : Node(KIntegerLiteral), Type(Type_), Value(Value_) {}2467 2468 template<typename Fn> void match(Fn F) const { F(Type, Value); }2469 2470 void printLeft(OutputBuffer &OB) const override {2471 if (Type.size() > 3) {2472 OB.printOpen();2473 OB += Type;2474 OB.printClose();2475 }2476 2477 if (Value[0] == 'n')2478 OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);2479 else2480 OB += Value;2481 2482 if (Type.size() <= 3)2483 OB += Type;2484 }2485 2486 std::string_view value() const { return Value; }2487};2488 2489class RequiresExpr : public Node {2490 NodeArray Parameters;2491 NodeArray Requirements;2492public:2493 RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)2494 : Node(KRequiresExpr), Parameters(Parameters_),2495 Requirements(Requirements_) {}2496 2497 template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }2498 2499 void printLeft(OutputBuffer &OB) const override {2500 OB += "requires";2501 if (!Parameters.empty()) {2502 OB += ' ';2503 OB.printOpen();2504 Parameters.printWithComma(OB);2505 OB.printClose();2506 }2507 OB += ' ';2508 OB.printOpen('{');2509 for (const Node *Req : Requirements) {2510 Req->print(OB);2511 }2512 OB += ' ';2513 OB.printClose('}');2514 }2515};2516 2517class ExprRequirement : public Node {2518 const Node *Expr;2519 bool IsNoexcept;2520 const Node *TypeConstraint;2521public:2522 ExprRequirement(const Node *Expr_, bool IsNoexcept_,2523 const Node *TypeConstraint_)2524 : Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),2525 TypeConstraint(TypeConstraint_) {}2526 2527 template <typename Fn> void match(Fn F) const {2528 F(Expr, IsNoexcept, TypeConstraint);2529 }2530 2531 void printLeft(OutputBuffer &OB) const override {2532 OB += " ";2533 if (IsNoexcept || TypeConstraint)2534 OB.printOpen('{');2535 Expr->print(OB);2536 if (IsNoexcept || TypeConstraint)2537 OB.printClose('}');2538 if (IsNoexcept)2539 OB += " noexcept";2540 if (TypeConstraint) {2541 OB += " -> ";2542 TypeConstraint->print(OB);2543 }2544 OB += ';';2545 }2546};2547 2548class TypeRequirement : public Node {2549 const Node *Type;2550public:2551 TypeRequirement(const Node *Type_)2552 : Node(KTypeRequirement), Type(Type_) {}2553 2554 template <typename Fn> void match(Fn F) const { F(Type); }2555 2556 void printLeft(OutputBuffer &OB) const override {2557 OB += " typename ";2558 Type->print(OB);2559 OB += ';';2560 }2561};2562 2563class NestedRequirement : public Node {2564 const Node *Constraint;2565public:2566 NestedRequirement(const Node *Constraint_)2567 : Node(KNestedRequirement), Constraint(Constraint_) {}2568 2569 template <typename Fn> void match(Fn F) const { F(Constraint); }2570 2571 void printLeft(OutputBuffer &OB) const override {2572 OB += " requires ";2573 Constraint->print(OB);2574 OB += ';';2575 }2576};2577 2578template <class Float> struct FloatData;2579 2580namespace float_literal_impl {2581constexpr Node::Kind getFloatLiteralKind(float *) {2582 return Node::KFloatLiteral;2583}2584constexpr Node::Kind getFloatLiteralKind(double *) {2585 return Node::KDoubleLiteral;2586}2587constexpr Node::Kind getFloatLiteralKind(long double *) {2588 return Node::KLongDoubleLiteral;2589}2590}2591 2592template <class Float> class FloatLiteralImpl : public Node {2593 const std::string_view Contents;2594 2595 static constexpr Kind KindForClass =2596 float_literal_impl::getFloatLiteralKind((Float *)nullptr);2597 2598public:2599 FloatLiteralImpl(std::string_view Contents_)2600 : Node(KindForClass), Contents(Contents_) {}2601 2602 template<typename Fn> void match(Fn F) const { F(Contents); }2603 2604 void printLeft(OutputBuffer &OB) const override {2605 const size_t N = FloatData<Float>::mangled_size;2606 if (Contents.size() >= N) {2607 union {2608 Float value;2609 char buf[sizeof(Float)];2610 };2611 const char *t = Contents.data();2612 const char *last = t + N;2613 char *e = buf;2614 for (; t != last; ++t, ++e) {2615 unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')2616 : static_cast<unsigned>(*t - 'a' + 10);2617 ++t;2618 unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')2619 : static_cast<unsigned>(*t - 'a' + 10);2620 *e = static_cast<char>((d1 << 4) + d0);2621 }2622#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__2623 std::reverse(buf, e);2624#endif2625 char num[FloatData<Float>::max_demangled_size] = {0};2626 int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);2627 OB += std::string_view(num, n);2628 }2629 }2630};2631 2632using FloatLiteral = FloatLiteralImpl<float>;2633using DoubleLiteral = FloatLiteralImpl<double>;2634using LongDoubleLiteral = FloatLiteralImpl<long double>;2635 2636/// Visit the node. Calls \c F(P), where \c P is the node cast to the2637/// appropriate derived class.2638template<typename Fn>2639void Node::visit(Fn F) const {2640 switch (K) {2641#define NODE(X) \2642 case K##X: \2643 return F(static_cast<const X *>(this));2644#include "ItaniumNodes.def"2645 }2646 DEMANGLE_ASSERT(0, "unknown mangling node kind");2647}2648 2649/// Determine the kind of a node from its type.2650template<typename NodeT> struct NodeKind;2651#define NODE(X) \2652 template <> struct NodeKind<X> { \2653 static constexpr Node::Kind Kind = Node::K##X; \2654 static constexpr const char *name() { return #X; } \2655 };2656#include "ItaniumNodes.def"2657 2658inline bool NodeArray::printAsString(OutputBuffer &OB) const {2659 auto StartPos = OB.getCurrentPosition();2660 auto Fail = [&OB, StartPos] {2661 OB.setCurrentPosition(StartPos);2662 return false;2663 };2664 2665 OB += '"';2666 bool LastWasNumericEscape = false;2667 for (const Node *Element : *this) {2668 if (Element->getKind() != Node::KIntegerLiteral)2669 return Fail();2670 int integer_value = 0;2671 for (char c : static_cast<const IntegerLiteral *>(Element)->value()) {2672 if (c < '0' || c > '9' || integer_value > 25)2673 return Fail();2674 integer_value *= 10;2675 integer_value += c - '0';2676 }2677 if (integer_value > 255)2678 return Fail();2679 2680 // Insert a `""` to avoid accidentally extending a numeric escape.2681 if (LastWasNumericEscape) {2682 if ((integer_value >= '0' && integer_value <= '9') ||2683 (integer_value >= 'a' && integer_value <= 'f') ||2684 (integer_value >= 'A' && integer_value <= 'F')) {2685 OB += "\"\"";2686 }2687 }2688 2689 LastWasNumericEscape = false;2690 2691 // Determine how to print this character.2692 switch (integer_value) {2693 case '\a':2694 OB += "\\a";2695 break;2696 case '\b':2697 OB += "\\b";2698 break;2699 case '\f':2700 OB += "\\f";2701 break;2702 case '\n':2703 OB += "\\n";2704 break;2705 case '\r':2706 OB += "\\r";2707 break;2708 case '\t':2709 OB += "\\t";2710 break;2711 case '\v':2712 OB += "\\v";2713 break;2714 2715 case '"':2716 OB += "\\\"";2717 break;2718 case '\\':2719 OB += "\\\\";2720 break;2721 2722 default:2723 // We assume that the character is ASCII, and use a numeric escape for all2724 // remaining non-printable ASCII characters.2725 if (integer_value < 32 || integer_value == 127) {2726 constexpr char Hex[] = "0123456789ABCDEF";2727 OB += '\\';2728 if (integer_value > 7)2729 OB += 'x';2730 if (integer_value >= 16)2731 OB += Hex[integer_value >> 4];2732 OB += Hex[integer_value & 0xF];2733 LastWasNumericEscape = true;2734 break;2735 }2736 2737 // Assume all remaining characters are directly printable.2738 OB += (char)integer_value;2739 break;2740 }2741 }2742 OB += '"';2743 return true;2744}2745 2746template <typename Derived, typename Alloc> struct AbstractManglingParser {2747 const char *First;2748 const char *Last;2749 2750 // Name stack, this is used by the parser to hold temporary names that were2751 // parsed. The parser collapses multiple names into new nodes to construct2752 // the AST. Once the parser is finished, names.size() == 1.2753 PODSmallVector<Node *, 32> Names;2754 2755 // Substitution table. Itanium supports name substitutions as a means of2756 // compression. The string "S42_" refers to the 44nd entry (base-36) in this2757 // table.2758 PODSmallVector<Node *, 32> Subs;2759 2760 // A list of template argument values corresponding to a template parameter2761 // list.2762 using TemplateParamList = PODSmallVector<Node *, 8>;2763 2764 class ScopedTemplateParamList {2765 AbstractManglingParser *Parser;2766 size_t OldNumTemplateParamLists;2767 TemplateParamList Params;2768 2769 public:2770 ScopedTemplateParamList(AbstractManglingParser *TheParser)2771 : Parser(TheParser),2772 OldNumTemplateParamLists(TheParser->TemplateParams.size()) {2773 Parser->TemplateParams.push_back(&Params);2774 }2775 ~ScopedTemplateParamList() {2776 DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,2777 "");2778 Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);2779 }2780 TemplateParamList *params() { return &Params; }2781 };2782 2783 // Template parameter table. Like the above, but referenced like "T42_".2784 // This has a smaller size compared to Subs and Names because it can be2785 // stored on the stack.2786 TemplateParamList OuterTemplateParams;2787 2788 // Lists of template parameters indexed by template parameter depth,2789 // referenced like "TL2_4_". If nonempty, element 0 is always2790 // OuterTemplateParams; inner elements are always template parameter lists of2791 // lambda expressions. For a generic lambda with no explicit template2792 // parameter list, the corresponding parameter list pointer will be null.2793 PODSmallVector<TemplateParamList *, 4> TemplateParams;2794 2795 class SaveTemplateParams {2796 AbstractManglingParser *Parser;2797 decltype(TemplateParams) OldParams;2798 decltype(OuterTemplateParams) OldOuterParams;2799 2800 public:2801 SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {2802 OldParams = std::move(Parser->TemplateParams);2803 OldOuterParams = std::move(Parser->OuterTemplateParams);2804 Parser->TemplateParams.clear();2805 Parser->OuterTemplateParams.clear();2806 }2807 ~SaveTemplateParams() {2808 Parser->TemplateParams = std::move(OldParams);2809 Parser->OuterTemplateParams = std::move(OldOuterParams);2810 }2811 };2812 2813 // Set of unresolved forward <template-param> references. These can occur in a2814 // conversion operator's type, and are resolved in the enclosing <encoding>.2815 PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;2816 2817 bool TryToParseTemplateArgs = true;2818 bool PermitForwardTemplateReferences = false;2819 bool HasIncompleteTemplateParameterTracking = false;2820 size_t ParsingLambdaParamsAtLevel = (size_t)-1;2821 2822 unsigned NumSyntheticTemplateParameters[3] = {};2823 2824 Alloc ASTAllocator;2825 2826 AbstractManglingParser(const char *First_, const char *Last_)2827 : First(First_), Last(Last_) {}2828 2829 Derived &getDerived() { return static_cast<Derived &>(*this); }2830 2831 void reset(const char *First_, const char *Last_) {2832 First = First_;2833 Last = Last_;2834 Names.clear();2835 Subs.clear();2836 TemplateParams.clear();2837 ParsingLambdaParamsAtLevel = (size_t)-1;2838 TryToParseTemplateArgs = true;2839 PermitForwardTemplateReferences = false;2840 for (int I = 0; I != 3; ++I)2841 NumSyntheticTemplateParameters[I] = 0;2842 ASTAllocator.reset();2843 }2844 2845 template <class T, class... Args> Node *make(Args &&... args) {2846 return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);2847 }2848 2849 template <class It> NodeArray makeNodeArray(It begin, It end) {2850 size_t sz = static_cast<size_t>(end - begin);2851 void *mem = ASTAllocator.allocateNodeArray(sz);2852 Node **data = new (mem) Node *[sz];2853 std::copy(begin, end, data);2854 return NodeArray(data, sz);2855 }2856 2857 NodeArray popTrailingNodeArray(size_t FromPosition) {2858 DEMANGLE_ASSERT(FromPosition <= Names.size(), "");2859 NodeArray res =2860 makeNodeArray(Names.begin() + (long)FromPosition, Names.end());2861 Names.shrinkToSize(FromPosition);2862 return res;2863 }2864 2865 bool consumeIf(std::string_view S) {2866 if (starts_with(std::string_view(First, Last - First), S)) {2867 First += S.size();2868 return true;2869 }2870 return false;2871 }2872 2873 bool consumeIf(char C) {2874 if (First != Last && *First == C) {2875 ++First;2876 return true;2877 }2878 return false;2879 }2880 2881 char consume() { return First != Last ? *First++ : '\0'; }2882 2883 char look(unsigned Lookahead = 0) const {2884 if (static_cast<size_t>(Last - First) <= Lookahead)2885 return '\0';2886 return First[Lookahead];2887 }2888 2889 size_t numLeft() const { return static_cast<size_t>(Last - First); }2890 2891 std::string_view parseNumber(bool AllowNegative = false);2892 Qualifiers parseCVQualifiers();2893 bool parsePositiveInteger(size_t *Out);2894 std::string_view parseBareSourceName();2895 2896 bool parseSeqId(size_t *Out);2897 Node *parseSubstitution();2898 Node *parseTemplateParam();2899 Node *parseTemplateParamDecl(TemplateParamList *Params);2900 Node *parseTemplateArgs(bool TagTemplates = false);2901 Node *parseTemplateArg();2902 2903 bool isTemplateParamDecl() {2904 return look() == 'T' &&2905 std::string_view("yptnk").find(look(1)) != std::string_view::npos;2906 }2907 2908 /// Parse the <expression> production.2909 Node *parseExpr();2910 Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);2911 Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);2912 Node *parseIntegerLiteral(std::string_view Lit);2913 Node *parseExprPrimary();2914 template <class Float> Node *parseFloatingLiteral();2915 Node *parseFunctionParam();2916 Node *parseConversionExpr();2917 Node *parseBracedExpr();2918 Node *parseFoldExpr();2919 Node *parsePointerToMemberConversionExpr(Node::Prec Prec);2920 Node *parseSubobjectExpr();2921 Node *parseConstraintExpr();2922 Node *parseRequiresExpr();2923 2924 /// Parse the <type> production.2925 Node *parseType();2926 Node *parseFunctionType();2927 Node *parseVectorType();2928 Node *parseDecltype();2929 Node *parseArrayType();2930 Node *parsePointerToMemberType();2931 Node *parseClassEnumType();2932 Node *parseQualifiedType();2933 2934 Node *parseEncoding(bool ParseParams = true);2935 bool parseCallOffset();2936 Node *parseSpecialName();2937 2938 /// Holds some extra information about a <name> that is being parsed. This2939 /// information is only pertinent if the <name> refers to an <encoding>.2940 struct NameState {2941 bool CtorDtorConversion = false;2942 bool EndsWithTemplateArgs = false;2943 Qualifiers CVQualifiers = QualNone;2944 FunctionRefQual ReferenceQualifier = FrefQualNone;2945 size_t ForwardTemplateRefsBegin;2946 bool HasExplicitObjectParameter = false;2947 2948 NameState(AbstractManglingParser *Enclosing)2949 : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}2950 };2951 2952 bool resolveForwardTemplateRefs(NameState &State) {2953 size_t I = State.ForwardTemplateRefsBegin;2954 size_t E = ForwardTemplateRefs.size();2955 for (; I < E; ++I) {2956 size_t Idx = ForwardTemplateRefs[I]->Index;2957 if (TemplateParams.empty() || !TemplateParams[0] ||2958 Idx >= TemplateParams[0]->size())2959 return true;2960 ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];2961 }2962 ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);2963 return false;2964 }2965 2966 /// Parse the <name> production>2967 Node *parseName(NameState *State = nullptr);2968 Node *parseLocalName(NameState *State);2969 Node *parseOperatorName(NameState *State);2970 bool parseModuleNameOpt(ModuleName *&Module);2971 Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);2972 Node *parseUnnamedTypeName(NameState *State);2973 Node *parseSourceName(NameState *State);2974 Node *parseUnscopedName(NameState *State, bool *isSubstName);2975 Node *parseNestedName(NameState *State);2976 Node *parseCtorDtorName(Node *&SoFar, NameState *State);2977 2978 Node *parseAbiTags(Node *N);2979 2980 struct OperatorInfo {2981 enum OIKind : unsigned char {2982 Prefix, // Prefix unary: @ expr2983 Postfix, // Postfix unary: expr @2984 Binary, // Binary: lhs @ rhs2985 Array, // Array index: lhs [ rhs ]2986 Member, // Member access: lhs @ rhs2987 New, // New2988 Del, // Delete2989 Call, // Function call: expr (expr*)2990 CCast, // C cast: (type)expr2991 Conditional, // Conditional: expr ? expr : expr2992 NameOnly, // Overload only, not allowed in expression.2993 // Below do not have operator names2994 NamedCast, // Named cast, @<type>(expr)2995 OfIdOp, // alignof, sizeof, typeid2996 2997 Unnameable = NamedCast,2998 };2999 char Enc[2]; // Encoding3000 OIKind Kind; // Kind of operator3001 bool Flag : 1; // Entry-specific flag3002 Node::Prec Prec : 7; // Precedence3003 const char *Name; // Spelling3004 3005 public:3006 constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,3007 const char *N)3008 : Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}3009 3010 public:3011 bool operator<(const OperatorInfo &Other) const {3012 return *this < Other.Enc;3013 }3014 bool operator<(const char *Peek) const {3015 return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);3016 }3017 bool operator==(const char *Peek) const {3018 return Enc[0] == Peek[0] && Enc[1] == Peek[1];3019 }3020 bool operator!=(const char *Peek) const { return !this->operator==(Peek); }3021 3022 public:3023 std::string_view getSymbol() const {3024 std::string_view Res = Name;3025 if (Kind < Unnameable) {3026 DEMANGLE_ASSERT(starts_with(Res, "operator"),3027 "operator name does not start with 'operator'");3028 Res.remove_prefix(sizeof("operator") - 1);3029 if (starts_with(Res, ' '))3030 Res.remove_prefix(1);3031 }3032 return Res;3033 }3034 std::string_view getName() const { return Name; }3035 OIKind getKind() const { return Kind; }3036 bool getFlag() const { return Flag; }3037 Node::Prec getPrecedence() const { return Prec; }3038 };3039 static const OperatorInfo Ops[];3040 static const size_t NumOps;3041 const OperatorInfo *parseOperatorEncoding();3042 3043 /// Parse the <unresolved-name> production.3044 Node *parseUnresolvedName(bool Global);3045 Node *parseSimpleId();3046 Node *parseBaseUnresolvedName();3047 Node *parseUnresolvedType();3048 Node *parseDestructorName();3049 3050 /// Top-level entry point into the parser.3051 Node *parse(bool ParseParams = true);3052};3053 3054DEMANGLE_ABI const char *parse_discriminator(const char *first,3055 const char *last);3056 3057// <name> ::= <nested-name> // N3058// ::= <local-name> # See Scope Encoding below // Z3059// ::= <unscoped-template-name> <template-args>3060// ::= <unscoped-name>3061//3062// <unscoped-template-name> ::= <unscoped-name>3063// ::= <substitution>3064template <typename Derived, typename Alloc>3065Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {3066 if (look() == 'N')3067 return getDerived().parseNestedName(State);3068 if (look() == 'Z')3069 return getDerived().parseLocalName(State);3070 3071 Node *Result = nullptr;3072 bool IsSubst = false;3073 3074 Result = getDerived().parseUnscopedName(State, &IsSubst);3075 if (!Result)3076 return nullptr;3077 3078 if (look() == 'I') {3079 // ::= <unscoped-template-name> <template-args>3080 if (!IsSubst)3081 // An unscoped-template-name is substitutable.3082 Subs.push_back(Result);3083 Node *TA = getDerived().parseTemplateArgs(State != nullptr);3084 if (TA == nullptr)3085 return nullptr;3086 if (State)3087 State->EndsWithTemplateArgs = true;3088 Result = make<NameWithTemplateArgs>(Result, TA);3089 } else if (IsSubst) {3090 // The substitution case must be followed by <template-args>.3091 return nullptr;3092 }3093 3094 return Result;3095}3096 3097// <local-name> := Z <function encoding> E <entity name> [<discriminator>]3098// := Z <function encoding> E s [<discriminator>]3099// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>3100template <typename Derived, typename Alloc>3101Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {3102 if (!consumeIf('Z'))3103 return nullptr;3104 Node *Encoding = getDerived().parseEncoding();3105 if (Encoding == nullptr || !consumeIf('E'))3106 return nullptr;3107 3108 if (consumeIf('s')) {3109 First = parse_discriminator(First, Last);3110 auto *StringLitName = make<NameType>("string literal");3111 if (!StringLitName)3112 return nullptr;3113 return make<LocalName>(Encoding, StringLitName);3114 }3115 3116 // The template parameters of the inner name are unrelated to those of the3117 // enclosing context.3118 SaveTemplateParams SaveTemplateParamsScope(this);3119 3120 if (consumeIf('d')) {3121 parseNumber(true);3122 if (!consumeIf('_'))3123 return nullptr;3124 Node *N = getDerived().parseName(State);3125 if (N == nullptr)3126 return nullptr;3127 return make<LocalName>(Encoding, N);3128 }3129 3130 Node *Entity = getDerived().parseName(State);3131 if (Entity == nullptr)3132 return nullptr;3133 First = parse_discriminator(First, Last);3134 return make<LocalName>(Encoding, Entity);3135}3136 3137// <unscoped-name> ::= <unqualified-name>3138// ::= St <unqualified-name> # ::std::3139// [*] extension3140template <typename Derived, typename Alloc>3141Node *3142AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,3143 bool *IsSubst) {3144 3145 Node *Std = nullptr;3146 if (consumeIf("St")) {3147 Std = make<NameType>("std");3148 if (Std == nullptr)3149 return nullptr;3150 }3151 3152 Node *Res = nullptr;3153 ModuleName *Module = nullptr;3154 if (look() == 'S') {3155 Node *S = getDerived().parseSubstitution();3156 if (!S)3157 return nullptr;3158 if (S->getKind() == Node::KModuleName)3159 Module = static_cast<ModuleName *>(S);3160 else if (IsSubst && Std == nullptr) {3161 Res = S;3162 *IsSubst = true;3163 } else {3164 return nullptr;3165 }3166 }3167 3168 if (Res == nullptr || Std != nullptr) {3169 Res = getDerived().parseUnqualifiedName(State, Std, Module);3170 }3171 3172 return Res;3173}3174 3175// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]3176// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]3177// ::= [<module-name>] F? L? <source-name> [<abi-tags>]3178// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]3179// # structured binding declaration3180// ::= [<module-name>] L? DC <source-name>+ E3181template <typename Derived, typename Alloc>3182Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(3183 NameState *State, Node *Scope, ModuleName *Module) {3184 if (getDerived().parseModuleNameOpt(Module))3185 return nullptr;3186 3187 bool IsMemberLikeFriend = Scope && consumeIf('F');3188 3189 consumeIf('L');3190 3191 Node *Result;3192 if (look() >= '1' && look() <= '9') {3193 Result = getDerived().parseSourceName(State);3194 } else if (look() == 'U') {3195 Result = getDerived().parseUnnamedTypeName(State);3196 } else if (consumeIf("DC")) {3197 // Structured binding3198 size_t BindingsBegin = Names.size();3199 do {3200 Node *Binding = getDerived().parseSourceName(State);3201 if (Binding == nullptr)3202 return nullptr;3203 Names.push_back(Binding);3204 } while (!consumeIf('E'));3205 Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));3206 } else if (look() == 'C' || look() == 'D') {3207 // A <ctor-dtor-name>.3208 if (Scope == nullptr || Module != nullptr)3209 return nullptr;3210 Result = getDerived().parseCtorDtorName(Scope, State);3211 } else {3212 Result = getDerived().parseOperatorName(State);3213 }3214 3215 if (Result != nullptr && Module != nullptr)3216 Result = make<ModuleEntity>(Module, Result);3217 if (Result != nullptr)3218 Result = getDerived().parseAbiTags(Result);3219 if (Result != nullptr && IsMemberLikeFriend)3220 Result = make<MemberLikeFriendName>(Scope, Result);3221 else if (Result != nullptr && Scope != nullptr)3222 Result = make<NestedName>(Scope, Result);3223 3224 return Result;3225}3226 3227// <module-name> ::= <module-subname>3228// ::= <module-name> <module-subname>3229// ::= <substitution> # passed in by caller3230// <module-subname> ::= W <source-name>3231// ::= W P <source-name>3232template <typename Derived, typename Alloc>3233bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(3234 ModuleName *&Module) {3235 while (consumeIf('W')) {3236 bool IsPartition = consumeIf('P');3237 Node *Sub = getDerived().parseSourceName(nullptr);3238 if (!Sub)3239 return true;3240 Module =3241 static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));3242 Subs.push_back(Module);3243 }3244 3245 return false;3246}3247 3248// <unnamed-type-name> ::= Ut [<nonnegative number>] _3249// ::= <closure-type-name>3250//3251// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _3252//3253// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]3254// <parameter type>+ # or "v" if the lambda has no parameters3255template <typename Derived, typename Alloc>3256Node *3257AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {3258 // <template-params> refer to the innermost <template-args>. Clear out any3259 // outer args that we may have inserted into TemplateParams.3260 if (State != nullptr)3261 TemplateParams.clear();3262 3263 if (consumeIf("Ut")) {3264 std::string_view Count = parseNumber();3265 if (!consumeIf('_'))3266 return nullptr;3267 return make<UnnamedTypeName>(Count);3268 }3269 if (consumeIf("Ul")) {3270 ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,3271 TemplateParams.size());3272 ScopedTemplateParamList LambdaTemplateParams(this);3273 3274 size_t ParamsBegin = Names.size();3275 while (getDerived().isTemplateParamDecl()) {3276 Node *T =3277 getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());3278 if (T == nullptr)3279 return nullptr;3280 Names.push_back(T);3281 }3282 NodeArray TempParams = popTrailingNodeArray(ParamsBegin);3283 3284 // FIXME: If TempParams is empty and none of the function parameters3285 // includes 'auto', we should remove LambdaTemplateParams from the3286 // TemplateParams list. Unfortunately, we don't find out whether there are3287 // any 'auto' parameters until too late in an example such as:3288 //3289 // template<typename T> void f(3290 // decltype([](decltype([]<typename T>(T v) {}),3291 // auto) {})) {}3292 // template<typename T> void f(3293 // decltype([](decltype([]<typename T>(T w) {}),3294 // int) {})) {}3295 //3296 // Here, the type of v is at level 2 but the type of w is at level 1. We3297 // don't find this out until we encounter the type of the next parameter.3298 //3299 // However, compilers can't actually cope with the former example in3300 // practice, and it's likely to be made ill-formed in future, so we don't3301 // need to support it here.3302 //3303 // If we encounter an 'auto' in the function parameter types, we will3304 // recreate a template parameter scope for it, but any intervening lambdas3305 // will be parsed in the 'wrong' template parameter depth.3306 if (TempParams.empty())3307 TemplateParams.pop_back();3308 3309 Node *Requires1 = nullptr;3310 if (consumeIf('Q')) {3311 Requires1 = getDerived().parseConstraintExpr();3312 if (Requires1 == nullptr)3313 return nullptr;3314 }3315 3316 if (!consumeIf("v")) {3317 do {3318 Node *P = getDerived().parseType();3319 if (P == nullptr)3320 return nullptr;3321 Names.push_back(P);3322 } while (look() != 'E' && look() != 'Q');3323 }3324 NodeArray Params = popTrailingNodeArray(ParamsBegin);3325 3326 Node *Requires2 = nullptr;3327 if (consumeIf('Q')) {3328 Requires2 = getDerived().parseConstraintExpr();3329 if (Requires2 == nullptr)3330 return nullptr;3331 }3332 3333 if (!consumeIf('E'))3334 return nullptr;3335 3336 std::string_view Count = parseNumber();3337 if (!consumeIf('_'))3338 return nullptr;3339 return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,3340 Count);3341 }3342 if (consumeIf("Ub")) {3343 (void)parseNumber();3344 if (!consumeIf('_'))3345 return nullptr;3346 return make<NameType>("'block-literal'");3347 }3348 return nullptr;3349}3350 3351// <source-name> ::= <positive length number> <identifier>3352template <typename Derived, typename Alloc>3353Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {3354 size_t Length = 0;3355 if (parsePositiveInteger(&Length))3356 return nullptr;3357 if (numLeft() < Length || Length == 0)3358 return nullptr;3359 std::string_view Name(First, Length);3360 First += Length;3361 if (starts_with(Name, "_GLOBAL__N"))3362 return make<NameType>("(anonymous namespace)");3363 return make<NameType>(Name);3364}3365 3366// Operator encodings3367template <typename Derived, typename Alloc>3368const typename AbstractManglingParser<3369 Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,3370 Alloc>::Ops[] = {3371 // Keep ordered by encoding3372 {"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},3373 {"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},3374 {"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},3375 {"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},3376 {"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},3377 {"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},3378 {"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,3379 "operator co_await"},3380 {"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},3381 {"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},3382 {"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix,3383 "operator()"},3384 {"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},3385 {"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},3386 {"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix,3387 "operator()"},3388 {"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast3389 {"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},3390 {"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,3391 "operator delete[]"},3392 {"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},3393 {"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},3394 {"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,3395 "operator delete"},3396 {"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,3397 "operator.*"},3398 {"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,3399 "operator."},3400 {"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},3401 {"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},3402 {"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},3403 {"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},3404 {"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},3405 {"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},3406 {"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},3407 {"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},3408 {"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},3409 {"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},3410 {"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},3411 {"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},3412 {"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},3413 {"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},3414 {"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,3415 "operator*"},3416 {"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},3417 {"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,3418 "operator new[]"},3419 {"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},3420 {"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},3421 {"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},3422 {"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},3423 {"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},3424 {"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},3425 {"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},3426 {"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},3427 {"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},3428 {"pm", OperatorInfo::Member, /*Named*/ true, Node::Prec::PtrMem,3429 "operator->*"},3430 {"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},3431 {"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},3432 {"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,3433 "operator->"},3434 {"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,3435 "operator?"},3436 {"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},3437 {"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},3438 {"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,3439 "reinterpret_cast"},3440 {"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,3441 "operator%"},3442 {"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},3443 {"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},3444 {"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},3445 {"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},3446 {"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},3447 {"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,3448 "typeid "},3449 {"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},3450};3451template <typename Derived, typename Alloc>3452const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /3453 sizeof(Ops[0]);3454 3455// If the next 2 chars are an operator encoding, consume them and return their3456// OperatorInfo. Otherwise return nullptr.3457template <typename Derived, typename Alloc>3458const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *3459AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {3460 if (numLeft() < 2)3461 return nullptr;3462 3463 // We can't use lower_bound as that can link to symbols in the C++ library,3464 // and this must remain independent of that.3465 size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.3466 while (upper != lower) {3467 size_t middle = (upper + lower) / 2;3468 if (Ops[middle] < First)3469 lower = middle + 1;3470 else3471 upper = middle;3472 }3473 if (Ops[lower] != First)3474 return nullptr;3475 3476 First += 2;3477 return &Ops[lower];3478}3479 3480// <operator-name> ::= See parseOperatorEncoding()3481// ::= li <source-name> # operator ""3482// ::= v <digit> <source-name> # vendor extended operator3483template <typename Derived, typename Alloc>3484Node *3485AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {3486 if (const auto *Op = parseOperatorEncoding()) {3487 if (Op->getKind() == OperatorInfo::CCast) {3488 // ::= cv <type> # (cast)3489 ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);3490 // If we're parsing an encoding, State != nullptr and the conversion3491 // operators' <type> could have a <template-param> that refers to some3492 // <template-arg>s further ahead in the mangled name.3493 ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,3494 PermitForwardTemplateReferences ||3495 State != nullptr);3496 Node *Ty = getDerived().parseType();3497 if (Ty == nullptr)3498 return nullptr;3499 if (State) State->CtorDtorConversion = true;3500 return make<ConversionOperatorType>(Ty);3501 }3502 3503 if (Op->getKind() >= OperatorInfo::Unnameable)3504 /* Not a nameable operator. */3505 return nullptr;3506 if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())3507 /* Not a nameable MemberExpr */3508 return nullptr;3509 3510 return make<NameType>(Op->getName());3511 }3512 3513 if (consumeIf("li")) {3514 // ::= li <source-name> # operator ""3515 Node *SN = getDerived().parseSourceName(State);3516 if (SN == nullptr)3517 return nullptr;3518 return make<LiteralOperator>(SN);3519 }3520 3521 if (consumeIf('v')) {3522 // ::= v <digit> <source-name> # vendor extended operator3523 if (look() >= '0' && look() <= '9') {3524 First++;3525 Node *SN = getDerived().parseSourceName(State);3526 if (SN == nullptr)3527 return nullptr;3528 return make<ConversionOperatorType>(SN);3529 }3530 return nullptr;3531 }3532 3533 return nullptr;3534}3535 3536// <ctor-dtor-name> ::= C1 # complete object constructor3537// ::= C2 # base object constructor3538// ::= C3 # complete object allocating constructor3539// extension ::= C4 # gcc old-style "[unified]" constructor3540// extension ::= C5 # the COMDAT used for ctors3541// ::= D0 # deleting destructor3542// ::= D1 # complete object destructor3543// ::= D2 # base object destructor3544// extension ::= D4 # gcc old-style "[unified]" destructor3545// extension ::= D5 # the COMDAT used for dtors3546template <typename Derived, typename Alloc>3547Node *3548AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,3549 NameState *State) {3550 if (SoFar->getKind() == Node::KSpecialSubstitution) {3551 // Expand the special substitution.3552 SoFar = make<ExpandedSpecialSubstitution>(3553 static_cast<SpecialSubstitution *>(SoFar));3554 if (!SoFar)3555 return nullptr;3556 }3557 3558 if (consumeIf('C')) {3559 bool IsInherited = consumeIf('I');3560 if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&3561 look() != '5')3562 return nullptr;3563 int Variant = look() - '0';3564 ++First;3565 if (State) State->CtorDtorConversion = true;3566 if (IsInherited) {3567 if (getDerived().parseName(State) == nullptr)3568 return nullptr;3569 }3570 return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);3571 }3572 3573 if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||3574 look(1) == '4' || look(1) == '5')) {3575 int Variant = look(1) - '0';3576 First += 2;3577 if (State) State->CtorDtorConversion = true;3578 return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);3579 }3580 3581 return nullptr;3582}3583 3584// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>3585// <unqualified-name> E3586// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>3587// <template-args> E3588//3589// <prefix> ::= <prefix> <unqualified-name>3590// ::= <template-prefix> <template-args>3591// ::= <template-param>3592// ::= <decltype>3593// ::= # empty3594// ::= <substitution>3595// ::= <prefix> <data-member-prefix>3596// [*] extension3597//3598// <data-member-prefix> := <member source-name> [<template-args>] M3599//3600// <template-prefix> ::= <prefix> <template unqualified-name>3601// ::= <template-param>3602// ::= <substitution>3603template <typename Derived, typename Alloc>3604Node *3605AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {3606 if (!consumeIf('N'))3607 return nullptr;3608 3609 // 'H' specifies that the encoding that follows3610 // has an explicit object parameter.3611 if (!consumeIf('H')) {3612 Qualifiers CVTmp = parseCVQualifiers();3613 if (State)3614 State->CVQualifiers = CVTmp;3615 3616 if (consumeIf('O')) {3617 if (State)3618 State->ReferenceQualifier = FrefQualRValue;3619 } else if (consumeIf('R')) {3620 if (State)3621 State->ReferenceQualifier = FrefQualLValue;3622 } else {3623 if (State)3624 State->ReferenceQualifier = FrefQualNone;3625 }3626 } else if (State) {3627 State->HasExplicitObjectParameter = true;3628 }3629 3630 Node *SoFar = nullptr;3631 while (!consumeIf('E')) {3632 if (State)3633 // Only set end-with-template on the case that does that.3634 State->EndsWithTemplateArgs = false;3635 3636 if (look() == 'T') {3637 // ::= <template-param>3638 if (SoFar != nullptr)3639 return nullptr; // Cannot have a prefix.3640 SoFar = getDerived().parseTemplateParam();3641 } else if (look() == 'I') {3642 // ::= <template-prefix> <template-args>3643 if (SoFar == nullptr)3644 return nullptr; // Must have a prefix.3645 Node *TA = getDerived().parseTemplateArgs(State != nullptr);3646 if (TA == nullptr)3647 return nullptr;3648 if (SoFar->getKind() == Node::KNameWithTemplateArgs)3649 // Semantically <template-args> <template-args> cannot be generated by a3650 // C++ entity. There will always be [something like] a name between3651 // them.3652 return nullptr;3653 if (State)3654 State->EndsWithTemplateArgs = true;3655 SoFar = make<NameWithTemplateArgs>(SoFar, TA);3656 } else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {3657 // ::= <decltype>3658 if (SoFar != nullptr)3659 return nullptr; // Cannot have a prefix.3660 SoFar = getDerived().parseDecltype();3661 } else {3662 ModuleName *Module = nullptr;3663 3664 if (look() == 'S') {3665 // ::= <substitution>3666 Node *S = nullptr;3667 if (look(1) == 't') {3668 First += 2;3669 S = make<NameType>("std");3670 } else {3671 S = getDerived().parseSubstitution();3672 }3673 if (!S)3674 return nullptr;3675 if (S->getKind() == Node::KModuleName) {3676 Module = static_cast<ModuleName *>(S);3677 } else if (SoFar != nullptr) {3678 return nullptr; // Cannot have a prefix.3679 } else {3680 SoFar = S;3681 continue; // Do not push a new substitution.3682 }3683 }3684 3685 // ::= [<prefix>] <unqualified-name>3686 SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);3687 }3688 3689 if (SoFar == nullptr)3690 return nullptr;3691 Subs.push_back(SoFar);3692 3693 // No longer used.3694 // <data-member-prefix> := <member source-name> [<template-args>] M3695 consumeIf('M');3696 }3697 3698 if (SoFar == nullptr || Subs.empty())3699 return nullptr;3700 3701 Subs.pop_back();3702 return SoFar;3703}3704 3705// <simple-id> ::= <source-name> [ <template-args> ]3706template <typename Derived, typename Alloc>3707Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {3708 Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);3709 if (SN == nullptr)3710 return nullptr;3711 if (look() == 'I') {3712 Node *TA = getDerived().parseTemplateArgs();3713 if (TA == nullptr)3714 return nullptr;3715 return make<NameWithTemplateArgs>(SN, TA);3716 }3717 return SN;3718}3719 3720// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())3721// ::= <simple-id> # e.g., ~A<2*N>3722template <typename Derived, typename Alloc>3723Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {3724 Node *Result;3725 if (std::isdigit(look()))3726 Result = getDerived().parseSimpleId();3727 else3728 Result = getDerived().parseUnresolvedType();3729 if (Result == nullptr)3730 return nullptr;3731 return make<DtorName>(Result);3732}3733 3734// <unresolved-type> ::= <template-param>3735// ::= <decltype>3736// ::= <substitution>3737template <typename Derived, typename Alloc>3738Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {3739 if (look() == 'T') {3740 Node *TP = getDerived().parseTemplateParam();3741 if (TP == nullptr)3742 return nullptr;3743 Subs.push_back(TP);3744 return TP;3745 }3746 if (look() == 'D') {3747 Node *DT = getDerived().parseDecltype();3748 if (DT == nullptr)3749 return nullptr;3750 Subs.push_back(DT);3751 return DT;3752 }3753 return getDerived().parseSubstitution();3754}3755 3756// <base-unresolved-name> ::= <simple-id> # unresolved name3757// extension ::= <operator-name> # unresolved operator-function-id3758// extension ::= <operator-name> <template-args> # unresolved operator template-id3759// ::= on <operator-name> # unresolved operator-function-id3760// ::= on <operator-name> <template-args> # unresolved operator template-id3761// ::= dn <destructor-name> # destructor or pseudo-destructor;3762// # e.g. ~X or ~X<N-1>3763template <typename Derived, typename Alloc>3764Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {3765 if (std::isdigit(look()))3766 return getDerived().parseSimpleId();3767 3768 if (consumeIf("dn"))3769 return getDerived().parseDestructorName();3770 3771 consumeIf("on");3772 3773 Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);3774 if (Oper == nullptr)3775 return nullptr;3776 if (look() == 'I') {3777 Node *TA = getDerived().parseTemplateArgs();3778 if (TA == nullptr)3779 return nullptr;3780 return make<NameWithTemplateArgs>(Oper, TA);3781 }3782 return Oper;3783}3784 3785// <unresolved-name>3786// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3787// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x3788// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3789// # A::x, N::y, A<T>::z; "gs" means leading "::"3790// [gs] has been parsed by caller.3791// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x3792// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>3793// # T::N::x /decltype(p)::N::x3794// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3795//3796// <unresolved-qualifier-level> ::= <simple-id>3797template <typename Derived, typename Alloc>3798Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {3799 Node *SoFar = nullptr;3800 3801 // srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3802 // srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3803 if (consumeIf("srN")) {3804 SoFar = getDerived().parseUnresolvedType();3805 if (SoFar == nullptr)3806 return nullptr;3807 3808 if (look() == 'I') {3809 Node *TA = getDerived().parseTemplateArgs();3810 if (TA == nullptr)3811 return nullptr;3812 SoFar = make<NameWithTemplateArgs>(SoFar, TA);3813 if (!SoFar)3814 return nullptr;3815 }3816 3817 while (!consumeIf('E')) {3818 Node *Qual = getDerived().parseSimpleId();3819 if (Qual == nullptr)3820 return nullptr;3821 SoFar = make<QualifiedName>(SoFar, Qual);3822 if (!SoFar)3823 return nullptr;3824 }3825 3826 Node *Base = getDerived().parseBaseUnresolvedName();3827 if (Base == nullptr)3828 return nullptr;3829 return make<QualifiedName>(SoFar, Base);3830 }3831 3832 // [gs] <base-unresolved-name> # x or (with "gs") ::x3833 if (!consumeIf("sr")) {3834 SoFar = getDerived().parseBaseUnresolvedName();3835 if (SoFar == nullptr)3836 return nullptr;3837 if (Global)3838 SoFar = make<GlobalQualifiedName>(SoFar);3839 return SoFar;3840 }3841 3842 // [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3843 if (std::isdigit(look())) {3844 do {3845 Node *Qual = getDerived().parseSimpleId();3846 if (Qual == nullptr)3847 return nullptr;3848 if (SoFar)3849 SoFar = make<QualifiedName>(SoFar, Qual);3850 else if (Global)3851 SoFar = make<GlobalQualifiedName>(Qual);3852 else3853 SoFar = Qual;3854 if (!SoFar)3855 return nullptr;3856 } while (!consumeIf('E'));3857 }3858 // sr <unresolved-type> <base-unresolved-name>3859 // sr <unresolved-type> <template-args> <base-unresolved-name>3860 else {3861 SoFar = getDerived().parseUnresolvedType();3862 if (SoFar == nullptr)3863 return nullptr;3864 3865 if (look() == 'I') {3866 Node *TA = getDerived().parseTemplateArgs();3867 if (TA == nullptr)3868 return nullptr;3869 SoFar = make<NameWithTemplateArgs>(SoFar, TA);3870 if (!SoFar)3871 return nullptr;3872 }3873 }3874 3875 DEMANGLE_ASSERT(SoFar != nullptr, "");3876 3877 Node *Base = getDerived().parseBaseUnresolvedName();3878 if (Base == nullptr)3879 return nullptr;3880 return make<QualifiedName>(SoFar, Base);3881}3882 3883// <abi-tags> ::= <abi-tag> [<abi-tags>]3884// <abi-tag> ::= B <source-name>3885template <typename Derived, typename Alloc>3886Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {3887 while (consumeIf('B')) {3888 std::string_view SN = parseBareSourceName();3889 if (SN.empty())3890 return nullptr;3891 N = make<AbiTagAttr>(N, SN);3892 if (!N)3893 return nullptr;3894 }3895 return N;3896}3897 3898// <number> ::= [n] <non-negative decimal integer>3899template <typename Alloc, typename Derived>3900std::string_view3901AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {3902 const char *Tmp = First;3903 if (AllowNegative)3904 consumeIf('n');3905 if (numLeft() == 0 || !std::isdigit(*First))3906 return std::string_view();3907 while (numLeft() != 0 && std::isdigit(*First))3908 ++First;3909 return std::string_view(Tmp, First - Tmp);3910}3911 3912// <positive length number> ::= [0-9]*3913template <typename Alloc, typename Derived>3914bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {3915 *Out = 0;3916 if (look() < '0' || look() > '9')3917 return true;3918 while (look() >= '0' && look() <= '9') {3919 *Out *= 10;3920 *Out += static_cast<size_t>(consume() - '0');3921 }3922 return false;3923}3924 3925template <typename Alloc, typename Derived>3926std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {3927 size_t Int = 0;3928 if (parsePositiveInteger(&Int) || numLeft() < Int)3929 return {};3930 std::string_view R(First, Int);3931 First += Int;3932 return R;3933}3934 3935// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E3936//3937// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())3938// ::= DO <expression> E # computed (instantiation-dependent) noexcept3939// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types3940//3941// <ref-qualifier> ::= R # & ref-qualifier3942// <ref-qualifier> ::= O # && ref-qualifier3943template <typename Derived, typename Alloc>3944Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {3945 Qualifiers CVQuals = parseCVQualifiers();3946 3947 Node *ExceptionSpec = nullptr;3948 if (consumeIf("Do")) {3949 ExceptionSpec = make<NameType>("noexcept");3950 if (!ExceptionSpec)3951 return nullptr;3952 } else if (consumeIf("DO")) {3953 Node *E = getDerived().parseExpr();3954 if (E == nullptr || !consumeIf('E'))3955 return nullptr;3956 ExceptionSpec = make<NoexceptSpec>(E);3957 if (!ExceptionSpec)3958 return nullptr;3959 } else if (consumeIf("Dw")) {3960 size_t SpecsBegin = Names.size();3961 while (!consumeIf('E')) {3962 Node *T = getDerived().parseType();3963 if (T == nullptr)3964 return nullptr;3965 Names.push_back(T);3966 }3967 ExceptionSpec =3968 make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));3969 if (!ExceptionSpec)3970 return nullptr;3971 }3972 3973 consumeIf("Dx"); // transaction safe3974 3975 if (!consumeIf('F'))3976 return nullptr;3977 consumeIf('Y'); // extern "C"3978 Node *ReturnType = getDerived().parseType();3979 if (ReturnType == nullptr)3980 return nullptr;3981 3982 FunctionRefQual ReferenceQualifier = FrefQualNone;3983 size_t ParamsBegin = Names.size();3984 while (true) {3985 if (consumeIf('E'))3986 break;3987 if (consumeIf('v'))3988 continue;3989 if (consumeIf("RE")) {3990 ReferenceQualifier = FrefQualLValue;3991 break;3992 }3993 if (consumeIf("OE")) {3994 ReferenceQualifier = FrefQualRValue;3995 break;3996 }3997 Node *T = getDerived().parseType();3998 if (T == nullptr)3999 return nullptr;4000 Names.push_back(T);4001 }4002 4003 NodeArray Params = popTrailingNodeArray(ParamsBegin);4004 return make<FunctionType>(ReturnType, Params, CVQuals,4005 ReferenceQualifier, ExceptionSpec);4006}4007 4008// extension:4009// <vector-type> ::= Dv <positive dimension number> _ <extended element type>4010// ::= Dv [<dimension expression>] _ <element type>4011// <extended element type> ::= <element type>4012// ::= p # AltiVec vector pixel4013template <typename Derived, typename Alloc>4014Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {4015 if (!consumeIf("Dv"))4016 return nullptr;4017 if (look() >= '1' && look() <= '9') {4018 Node *DimensionNumber = make<NameType>(parseNumber());4019 if (!DimensionNumber)4020 return nullptr;4021 if (!consumeIf('_'))4022 return nullptr;4023 if (consumeIf('p'))4024 return make<PixelVectorType>(DimensionNumber);4025 Node *ElemType = getDerived().parseType();4026 if (ElemType == nullptr)4027 return nullptr;4028 return make<VectorType>(ElemType, DimensionNumber);4029 }4030 4031 if (!consumeIf('_')) {4032 Node *DimExpr = getDerived().parseExpr();4033 if (!DimExpr)4034 return nullptr;4035 if (!consumeIf('_'))4036 return nullptr;4037 Node *ElemType = getDerived().parseType();4038 if (!ElemType)4039 return nullptr;4040 return make<VectorType>(ElemType, DimExpr);4041 }4042 Node *ElemType = getDerived().parseType();4043 if (!ElemType)4044 return nullptr;4045 return make<VectorType>(ElemType, /*Dimension=*/nullptr);4046}4047 4048// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)4049// ::= DT <expression> E # decltype of an expression (C++0x)4050template <typename Derived, typename Alloc>4051Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {4052 if (!consumeIf('D'))4053 return nullptr;4054 if (!consumeIf('t') && !consumeIf('T'))4055 return nullptr;4056 Node *E = getDerived().parseExpr();4057 if (E == nullptr)4058 return nullptr;4059 if (!consumeIf('E'))4060 return nullptr;4061 return make<EnclosingExpr>("decltype", E);4062}4063 4064// <array-type> ::= A <positive dimension number> _ <element type>4065// ::= A [<dimension expression>] _ <element type>4066template <typename Derived, typename Alloc>4067Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {4068 if (!consumeIf('A'))4069 return nullptr;4070 4071 Node *Dimension = nullptr;4072 4073 if (std::isdigit(look())) {4074 Dimension = make<NameType>(parseNumber());4075 if (!Dimension)4076 return nullptr;4077 if (!consumeIf('_'))4078 return nullptr;4079 } else if (!consumeIf('_')) {4080 Node *DimExpr = getDerived().parseExpr();4081 if (DimExpr == nullptr)4082 return nullptr;4083 if (!consumeIf('_'))4084 return nullptr;4085 Dimension = DimExpr;4086 }4087 4088 Node *Ty = getDerived().parseType();4089 if (Ty == nullptr)4090 return nullptr;4091 return make<ArrayType>(Ty, Dimension);4092}4093 4094// <pointer-to-member-type> ::= M <class type> <member type>4095template <typename Derived, typename Alloc>4096Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {4097 if (!consumeIf('M'))4098 return nullptr;4099 Node *ClassType = getDerived().parseType();4100 if (ClassType == nullptr)4101 return nullptr;4102 Node *MemberType = getDerived().parseType();4103 if (MemberType == nullptr)4104 return nullptr;4105 return make<PointerToMemberType>(ClassType, MemberType);4106}4107 4108// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier4109// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'4110// ::= Tu <name> # dependent elaborated type specifier using 'union'4111// ::= Te <name> # dependent elaborated type specifier using 'enum'4112template <typename Derived, typename Alloc>4113Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {4114 std::string_view ElabSpef;4115 if (consumeIf("Ts"))4116 ElabSpef = "struct";4117 else if (consumeIf("Tu"))4118 ElabSpef = "union";4119 else if (consumeIf("Te"))4120 ElabSpef = "enum";4121 4122 Node *Name = getDerived().parseName();4123 if (Name == nullptr)4124 return nullptr;4125 4126 if (!ElabSpef.empty())4127 return make<ElaboratedTypeSpefType>(ElabSpef, Name);4128 4129 return Name;4130}4131 4132// <qualified-type> ::= <qualifiers> <type>4133// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>4134// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier4135template <typename Derived, typename Alloc>4136Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {4137 if (consumeIf('U')) {4138 std::string_view Qual = parseBareSourceName();4139 if (Qual.empty())4140 return nullptr;4141 4142 // extension ::= U <objc-name> <objc-type> # objc-type<identifier>4143 if (starts_with(Qual, "objcproto")) {4144 constexpr size_t Len = sizeof("objcproto") - 1;4145 std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);4146 std::string_view Proto;4147 {4148 ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),4149 SaveLast(Last, &*ProtoSourceName.rbegin() + 1);4150 Proto = parseBareSourceName();4151 }4152 if (Proto.empty())4153 return nullptr;4154 Node *Child = getDerived().parseQualifiedType();4155 if (Child == nullptr)4156 return nullptr;4157 return make<ObjCProtoName>(Child, Proto);4158 }4159 4160 Node *TA = nullptr;4161 if (look() == 'I') {4162 TA = getDerived().parseTemplateArgs();4163 if (TA == nullptr)4164 return nullptr;4165 }4166 4167 Node *Child = getDerived().parseQualifiedType();4168 if (Child == nullptr)4169 return nullptr;4170 return make<VendorExtQualType>(Child, Qual, TA);4171 }4172 4173 Qualifiers Quals = parseCVQualifiers();4174 Node *Ty = getDerived().parseType();4175 if (Ty == nullptr)4176 return nullptr;4177 if (Quals != QualNone)4178 Ty = make<QualType>(Ty, Quals);4179 return Ty;4180}4181 4182// <type> ::= <builtin-type>4183// ::= <qualified-type>4184// ::= <function-type>4185// ::= <class-enum-type>4186// ::= <array-type>4187// ::= <pointer-to-member-type>4188// ::= <template-param>4189// ::= <template-template-param> <template-args>4190// ::= <decltype>4191// ::= P <type> # pointer4192// ::= R <type> # l-value reference4193// ::= O <type> # r-value reference (C++11)4194// ::= C <type> # complex pair (C99)4195// ::= G <type> # imaginary (C99)4196// ::= <substitution> # See Compression below4197// extension ::= U <objc-name> <objc-type> # objc-type<identifier>4198// extension ::= <vector-type> # <vector-type> starts with Dv4199//4200// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k14201// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>4202template <typename Derived, typename Alloc>4203Node *AbstractManglingParser<Derived, Alloc>::parseType() {4204 Node *Result = nullptr;4205 4206 switch (look()) {4207 // ::= <qualified-type>4208 case 'r':4209 case 'V':4210 case 'K': {4211 unsigned AfterQuals = 0;4212 if (look(AfterQuals) == 'r') ++AfterQuals;4213 if (look(AfterQuals) == 'V') ++AfterQuals;4214 if (look(AfterQuals) == 'K') ++AfterQuals;4215 4216 if (look(AfterQuals) == 'F' ||4217 (look(AfterQuals) == 'D' &&4218 (look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||4219 look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {4220 Result = getDerived().parseFunctionType();4221 break;4222 }4223 DEMANGLE_FALLTHROUGH;4224 }4225 case 'U': {4226 Result = getDerived().parseQualifiedType();4227 break;4228 }4229 // <builtin-type> ::= v # void4230 case 'v':4231 ++First;4232 return make<NameType>("void");4233 // ::= w # wchar_t4234 case 'w':4235 ++First;4236 return make<NameType>("wchar_t");4237 // ::= b # bool4238 case 'b':4239 ++First;4240 return make<NameType>("bool");4241 // ::= c # char4242 case 'c':4243 ++First;4244 return make<NameType>("char");4245 // ::= a # signed char4246 case 'a':4247 ++First;4248 return make<NameType>("signed char");4249 // ::= h # unsigned char4250 case 'h':4251 ++First;4252 return make<NameType>("unsigned char");4253 // ::= s # short4254 case 's':4255 ++First;4256 return make<NameType>("short");4257 // ::= t # unsigned short4258 case 't':4259 ++First;4260 return make<NameType>("unsigned short");4261 // ::= i # int4262 case 'i':4263 ++First;4264 return make<NameType>("int");4265 // ::= j # unsigned int4266 case 'j':4267 ++First;4268 return make<NameType>("unsigned int");4269 // ::= l # long4270 case 'l':4271 ++First;4272 return make<NameType>("long");4273 // ::= m # unsigned long4274 case 'm':4275 ++First;4276 return make<NameType>("unsigned long");4277 // ::= x # long long, __int644278 case 'x':4279 ++First;4280 return make<NameType>("long long");4281 // ::= y # unsigned long long, __int644282 case 'y':4283 ++First;4284 return make<NameType>("unsigned long long");4285 // ::= n # __int1284286 case 'n':4287 ++First;4288 return make<NameType>("__int128");4289 // ::= o # unsigned __int1284290 case 'o':4291 ++First;4292 return make<NameType>("unsigned __int128");4293 // ::= f # float4294 case 'f':4295 ++First;4296 return make<NameType>("float");4297 // ::= d # double4298 case 'd':4299 ++First;4300 return make<NameType>("double");4301 // ::= e # long double, __float804302 case 'e':4303 ++First;4304 return make<NameType>("long double");4305 // ::= g # __float1284306 case 'g':4307 ++First;4308 return make<NameType>("__float128");4309 // ::= z # ellipsis4310 case 'z':4311 ++First;4312 return make<NameType>("...");4313 4314 // <builtin-type> ::= u <source-name> # vendor extended type4315 case 'u': {4316 ++First;4317 std::string_view Res = parseBareSourceName();4318 if (Res.empty())4319 return nullptr;4320 // Typically, <builtin-type>s are not considered substitution candidates,4321 // but the exception to that exception is vendor extended types (Itanium C++4322 // ABI 5.9.1).4323 if (consumeIf('I')) {4324 Node *BaseType = parseType();4325 if (BaseType == nullptr)4326 return nullptr;4327 if (!consumeIf('E'))4328 return nullptr;4329 Result = make<TransformedType>(Res, BaseType);4330 } else4331 Result = make<NameType>(Res);4332 break;4333 }4334 case 'D':4335 switch (look(1)) {4336 // ::= Dd # IEEE 754r decimal floating point (64 bits)4337 case 'd':4338 First += 2;4339 return make<NameType>("decimal64");4340 // ::= De # IEEE 754r decimal floating point (128 bits)4341 case 'e':4342 First += 2;4343 return make<NameType>("decimal128");4344 // ::= Df # IEEE 754r decimal floating point (32 bits)4345 case 'f':4346 First += 2;4347 return make<NameType>("decimal32");4348 // ::= Dh # IEEE 754r half-precision floating point (16 bits)4349 case 'h':4350 First += 2;4351 return make<NameType>("half");4352 // ::= DF16b # C++23 std::bfloat16_t4353 // ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)4354 case 'F': {4355 First += 2;4356 if (consumeIf("16b"))4357 return make<NameType>("std::bfloat16_t");4358 Node *DimensionNumber = make<NameType>(parseNumber());4359 if (!DimensionNumber)4360 return nullptr;4361 if (!consumeIf('_'))4362 return nullptr;4363 return make<BinaryFPType>(DimensionNumber);4364 }4365 // ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum4366 // ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac4367 // <fixed-point-size>4368 // ::= s # short4369 // ::= t # unsigned short4370 // ::= i # plain4371 // ::= j # unsigned4372 // ::= l # long4373 // ::= m # unsigned long4374 case 'A': {4375 char c = look(2);4376 First += 3;4377 switch (c) {4378 case 's':4379 return make<NameType>("short _Accum");4380 case 't':4381 return make<NameType>("unsigned short _Accum");4382 case 'i':4383 return make<NameType>("_Accum");4384 case 'j':4385 return make<NameType>("unsigned _Accum");4386 case 'l':4387 return make<NameType>("long _Accum");4388 case 'm':4389 return make<NameType>("unsigned long _Accum");4390 default:4391 return nullptr;4392 }4393 }4394 case 'R': {4395 char c = look(2);4396 First += 3;4397 switch (c) {4398 case 's':4399 return make<NameType>("short _Fract");4400 case 't':4401 return make<NameType>("unsigned short _Fract");4402 case 'i':4403 return make<NameType>("_Fract");4404 case 'j':4405 return make<NameType>("unsigned _Fract");4406 case 'l':4407 return make<NameType>("long _Fract");4408 case 'm':4409 return make<NameType>("unsigned long _Fract");4410 default:4411 return nullptr;4412 }4413 }4414 case 'S': {4415 First += 2;4416 if (look() != 'D')4417 return nullptr;4418 if (look(1) == 'A') {4419 char c = look(2);4420 First += 3;4421 switch (c) {4422 case 's':4423 return make<NameType>("_Sat short _Accum");4424 case 't':4425 return make<NameType>("_Sat unsigned short _Accum");4426 case 'i':4427 return make<NameType>("_Sat _Accum");4428 case 'j':4429 return make<NameType>("_Sat unsigned _Accum");4430 case 'l':4431 return make<NameType>("_Sat long _Accum");4432 case 'm':4433 return make<NameType>("_Sat unsigned long _Accum");4434 default:4435 return nullptr;4436 }4437 }4438 if (look(1) == 'R') {4439 char c = look(2);4440 First += 3;4441 switch (c) {4442 case 's':4443 return make<NameType>("_Sat short _Fract");4444 case 't':4445 return make<NameType>("_Sat unsigned short _Fract");4446 case 'i':4447 return make<NameType>("_Sat _Fract");4448 case 'j':4449 return make<NameType>("_Sat unsigned _Fract");4450 case 'l':4451 return make<NameType>("_Sat long _Fract");4452 case 'm':4453 return make<NameType>("_Sat unsigned long _Fract");4454 default:4455 return nullptr;4456 }4457 }4458 return nullptr;4459 }4460 // ::= DB <number> _ # C23 signed _BitInt(N)4461 // ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)4462 // ::= DU <number> _ # C23 unsigned _BitInt(N)4463 // ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)4464 case 'B':4465 case 'U': {4466 bool Signed = look(1) == 'B';4467 First += 2;4468 Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())4469 : getDerived().parseExpr();4470 if (!Size)4471 return nullptr;4472 if (!consumeIf('_'))4473 return nullptr;4474 // The front end expects this to be available for Substitution4475 Result = make<BitIntType>(Size, Signed);4476 break;4477 }4478 // ::= Di # char32_t4479 case 'i':4480 First += 2;4481 return make<NameType>("char32_t");4482 // ::= Ds # char16_t4483 case 's':4484 First += 2;4485 return make<NameType>("char16_t");4486 // ::= Du # char8_t (C++2a, not yet in the Itanium spec)4487 case 'u':4488 First += 2;4489 return make<NameType>("char8_t");4490 // ::= Da # auto (in dependent new-expressions)4491 case 'a':4492 First += 2;4493 return make<NameType>("auto");4494 // ::= Dc # decltype(auto)4495 case 'c':4496 First += 2;4497 return make<NameType>("decltype(auto)");4498 // ::= Dk <type-constraint> # constrained auto4499 // ::= DK <type-constraint> # constrained decltype(auto)4500 case 'k':4501 case 'K': {4502 std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";4503 First += 2;4504 Node *Constraint = getDerived().parseName();4505 if (!Constraint)4506 return nullptr;4507 return make<PostfixQualifiedType>(Constraint, Kind);4508 }4509 // ::= Dn # std::nullptr_t (i.e., decltype(nullptr))4510 case 'n':4511 First += 2;4512 return make<NameType>("std::nullptr_t");4513 4514 // ::= <decltype>4515 case 't':4516 case 'T': {4517 Result = getDerived().parseDecltype();4518 break;4519 }4520 // extension ::= <vector-type> # <vector-type> starts with Dv4521 case 'v': {4522 Result = getDerived().parseVectorType();4523 break;4524 }4525 // ::= Dp <type> # pack expansion (C++0x)4526 case 'p': {4527 First += 2;4528 Node *Child = getDerived().parseType();4529 if (!Child)4530 return nullptr;4531 Result = make<ParameterPackExpansion>(Child);4532 break;4533 }4534 // Exception specifier on a function type.4535 case 'o':4536 case 'O':4537 case 'w':4538 // Transaction safe function type.4539 case 'x':4540 Result = getDerived().parseFunctionType();4541 break;4542 }4543 break;4544 // ::= <function-type>4545 case 'F': {4546 Result = getDerived().parseFunctionType();4547 break;4548 }4549 // ::= <array-type>4550 case 'A': {4551 Result = getDerived().parseArrayType();4552 break;4553 }4554 // ::= <pointer-to-member-type>4555 case 'M': {4556 Result = getDerived().parsePointerToMemberType();4557 break;4558 }4559 // ::= <template-param>4560 case 'T': {4561 // This could be an elaborate type specifier on a <class-enum-type>.4562 if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {4563 Result = getDerived().parseClassEnumType();4564 break;4565 }4566 4567 Result = getDerived().parseTemplateParam();4568 if (Result == nullptr)4569 return nullptr;4570 4571 // Result could be either of:4572 // <type> ::= <template-param>4573 // <type> ::= <template-template-param> <template-args>4574 //4575 // <template-template-param> ::= <template-param>4576 // ::= <substitution>4577 //4578 // If this is followed by some <template-args>, and we're permitted to4579 // parse them, take the second production.4580 4581 if (TryToParseTemplateArgs && look() == 'I') {4582 Subs.push_back(Result);4583 Node *TA = getDerived().parseTemplateArgs();4584 if (TA == nullptr)4585 return nullptr;4586 Result = make<NameWithTemplateArgs>(Result, TA);4587 }4588 break;4589 }4590 // ::= P <type> # pointer4591 case 'P': {4592 ++First;4593 Node *Ptr = getDerived().parseType();4594 if (Ptr == nullptr)4595 return nullptr;4596 Result = make<PointerType>(Ptr);4597 break;4598 }4599 // ::= R <type> # l-value reference4600 case 'R': {4601 ++First;4602 Node *Ref = getDerived().parseType();4603 if (Ref == nullptr)4604 return nullptr;4605 Result = make<ReferenceType>(Ref, ReferenceKind::LValue);4606 break;4607 }4608 // ::= O <type> # r-value reference (C++11)4609 case 'O': {4610 ++First;4611 Node *Ref = getDerived().parseType();4612 if (Ref == nullptr)4613 return nullptr;4614 Result = make<ReferenceType>(Ref, ReferenceKind::RValue);4615 break;4616 }4617 // ::= C <type> # complex pair (C99)4618 case 'C': {4619 ++First;4620 Node *P = getDerived().parseType();4621 if (P == nullptr)4622 return nullptr;4623 Result = make<PostfixQualifiedType>(P, " complex");4624 break;4625 }4626 // ::= G <type> # imaginary (C99)4627 case 'G': {4628 ++First;4629 Node *P = getDerived().parseType();4630 if (P == nullptr)4631 return P;4632 Result = make<PostfixQualifiedType>(P, " imaginary");4633 break;4634 }4635 // ::= <substitution> # See Compression below4636 case 'S': {4637 if (look(1) != 't') {4638 bool IsSubst = false;4639 Result = getDerived().parseUnscopedName(nullptr, &IsSubst);4640 if (!Result)4641 return nullptr;4642 4643 // Sub could be either of:4644 // <type> ::= <substitution>4645 // <type> ::= <template-template-param> <template-args>4646 //4647 // <template-template-param> ::= <template-param>4648 // ::= <substitution>4649 //4650 // If this is followed by some <template-args>, and we're permitted to4651 // parse them, take the second production.4652 4653 if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {4654 if (!IsSubst)4655 Subs.push_back(Result);4656 Node *TA = getDerived().parseTemplateArgs();4657 if (TA == nullptr)4658 return nullptr;4659 Result = make<NameWithTemplateArgs>(Result, TA);4660 } else if (IsSubst) {4661 // If all we parsed was a substitution, don't re-insert into the4662 // substitution table.4663 return Result;4664 }4665 break;4666 }4667 DEMANGLE_FALLTHROUGH;4668 }4669 // ::= <class-enum-type>4670 default: {4671 Result = getDerived().parseClassEnumType();4672 break;4673 }4674 }4675 4676 // If we parsed a type, insert it into the substitution table. Note that all4677 // <builtin-type>s and <substitution>s have already bailed out, because they4678 // don't get substitutions.4679 if (Result != nullptr)4680 Subs.push_back(Result);4681 return Result;4682}4683 4684template <typename Derived, typename Alloc>4685Node *4686AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,4687 Node::Prec Prec) {4688 Node *E = getDerived().parseExpr();4689 if (E == nullptr)4690 return nullptr;4691 return make<PrefixExpr>(Kind, E, Prec);4692}4693 4694template <typename Derived, typename Alloc>4695Node *4696AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,4697 Node::Prec Prec) {4698 Node *LHS = getDerived().parseExpr();4699 if (LHS == nullptr)4700 return nullptr;4701 Node *RHS = getDerived().parseExpr();4702 if (RHS == nullptr)4703 return nullptr;4704 return make<BinaryExpr>(LHS, Kind, RHS, Prec);4705}4706 4707template <typename Derived, typename Alloc>4708Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(4709 std::string_view Lit) {4710 std::string_view Tmp = parseNumber(true);4711 if (!Tmp.empty() && consumeIf('E'))4712 return make<IntegerLiteral>(Lit, Tmp);4713 return nullptr;4714}4715 4716// <CV-Qualifiers> ::= [r] [V] [K]4717template <typename Alloc, typename Derived>4718Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {4719 Qualifiers CVR = QualNone;4720 if (consumeIf('r'))4721 CVR |= QualRestrict;4722 if (consumeIf('V'))4723 CVR |= QualVolatile;4724 if (consumeIf('K'))4725 CVR |= QualConst;4726 return CVR;4727}4728 4729// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter4730// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters4731// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter4732// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters4733// ::= fpT # 'this' expression (not part of standard?)4734template <typename Derived, typename Alloc>4735Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {4736 if (consumeIf("fpT"))4737 return make<NameType>("this");4738 if (consumeIf("fp")) {4739 parseCVQualifiers();4740 std::string_view Num = parseNumber();4741 if (!consumeIf('_'))4742 return nullptr;4743 return make<FunctionParam>(Num);4744 }4745 if (consumeIf("fL")) {4746 if (parseNumber().empty())4747 return nullptr;4748 if (!consumeIf('p'))4749 return nullptr;4750 parseCVQualifiers();4751 std::string_view Num = parseNumber();4752 if (!consumeIf('_'))4753 return nullptr;4754 return make<FunctionParam>(Num);4755 }4756 return nullptr;4757}4758 4759// cv <type> <expression> # conversion with one argument4760// cv <type> _ <expression>* E # conversion with a different number of arguments4761template <typename Derived, typename Alloc>4762Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {4763 if (!consumeIf("cv"))4764 return nullptr;4765 Node *Ty;4766 {4767 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);4768 Ty = getDerived().parseType();4769 }4770 4771 if (Ty == nullptr)4772 return nullptr;4773 4774 if (consumeIf('_')) {4775 size_t ExprsBegin = Names.size();4776 while (!consumeIf('E')) {4777 Node *E = getDerived().parseExpr();4778 if (E == nullptr)4779 return E;4780 Names.push_back(E);4781 }4782 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);4783 return make<ConversionExpr>(Ty, Exprs);4784 }4785 4786 Node *E[1] = {getDerived().parseExpr()};4787 if (E[0] == nullptr)4788 return nullptr;4789 return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));4790}4791 4792// <expr-primary> ::= L <type> <value number> E # integer literal4793// ::= L <type> <value float> E # floating literal4794// ::= L <string type> E # string literal4795// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")4796// ::= L <lambda type> E # lambda expression4797// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)4798// ::= L <mangled-name> E # external name4799template <typename Derived, typename Alloc>4800Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {4801 if (!consumeIf('L'))4802 return nullptr;4803 switch (look()) {4804 case 'w':4805 ++First;4806 return getDerived().parseIntegerLiteral("wchar_t");4807 case 'b':4808 if (consumeIf("b0E"))4809 return make<BoolExpr>(0);4810 if (consumeIf("b1E"))4811 return make<BoolExpr>(1);4812 return nullptr;4813 case 'c':4814 ++First;4815 return getDerived().parseIntegerLiteral("char");4816 case 'a':4817 ++First;4818 return getDerived().parseIntegerLiteral("signed char");4819 case 'h':4820 ++First;4821 return getDerived().parseIntegerLiteral("unsigned char");4822 case 's':4823 ++First;4824 return getDerived().parseIntegerLiteral("short");4825 case 't':4826 ++First;4827 return getDerived().parseIntegerLiteral("unsigned short");4828 case 'i':4829 ++First;4830 return getDerived().parseIntegerLiteral("");4831 case 'j':4832 ++First;4833 return getDerived().parseIntegerLiteral("u");4834 case 'l':4835 ++First;4836 return getDerived().parseIntegerLiteral("l");4837 case 'm':4838 ++First;4839 return getDerived().parseIntegerLiteral("ul");4840 case 'x':4841 ++First;4842 return getDerived().parseIntegerLiteral("ll");4843 case 'y':4844 ++First;4845 return getDerived().parseIntegerLiteral("ull");4846 case 'n':4847 ++First;4848 return getDerived().parseIntegerLiteral("__int128");4849 case 'o':4850 ++First;4851 return getDerived().parseIntegerLiteral("unsigned __int128");4852 case 'f':4853 ++First;4854 return getDerived().template parseFloatingLiteral<float>();4855 case 'd':4856 ++First;4857 return getDerived().template parseFloatingLiteral<double>();4858 case 'e':4859 ++First;4860#if defined(__powerpc__) || defined(__s390__)4861 // Handle cases where long doubles encoded with e have the same size4862 // and representation as doubles.4863 return getDerived().template parseFloatingLiteral<double>();4864#else4865 return getDerived().template parseFloatingLiteral<long double>();4866#endif4867 case '_':4868 if (consumeIf("_Z")) {4869 Node *R = getDerived().parseEncoding();4870 if (R != nullptr && consumeIf('E'))4871 return R;4872 }4873 return nullptr;4874 case 'A': {4875 Node *T = getDerived().parseType();4876 if (T == nullptr)4877 return nullptr;4878 // FIXME: We need to include the string contents in the mangling.4879 if (consumeIf('E'))4880 return make<StringLiteral>(T);4881 return nullptr;4882 }4883 case 'D':4884 if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))4885 return make<NameType>("nullptr");4886 return nullptr;4887 case 'T':4888 // Invalid mangled name per4889 // http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html4890 return nullptr;4891 case 'U': {4892 // FIXME: Should we support LUb... for block literals?4893 if (look(1) != 'l')4894 return nullptr;4895 Node *T = parseUnnamedTypeName(nullptr);4896 if (!T || !consumeIf('E'))4897 return nullptr;4898 return make<LambdaExpr>(T);4899 }4900 default: {4901 // might be named type4902 Node *T = getDerived().parseType();4903 if (T == nullptr)4904 return nullptr;4905 std::string_view N = parseNumber(/*AllowNegative=*/true);4906 if (N.empty())4907 return nullptr;4908 if (!consumeIf('E'))4909 return nullptr;4910 return make<EnumLiteral>(T, N);4911 }4912 }4913}4914 4915// <braced-expression> ::= <expression>4916// ::= di <field source-name> <braced-expression> # .name = expr4917// ::= dx <index expression> <braced-expression> # [expr] = expr4918// ::= dX <range begin expression> <range end expression> <braced-expression>4919template <typename Derived, typename Alloc>4920Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {4921 if (look() == 'd') {4922 switch (look(1)) {4923 case 'i': {4924 First += 2;4925 Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);4926 if (Field == nullptr)4927 return nullptr;4928 Node *Init = getDerived().parseBracedExpr();4929 if (Init == nullptr)4930 return nullptr;4931 return make<BracedExpr>(Field, Init, /*isArray=*/false);4932 }4933 case 'x': {4934 First += 2;4935 Node *Index = getDerived().parseExpr();4936 if (Index == nullptr)4937 return nullptr;4938 Node *Init = getDerived().parseBracedExpr();4939 if (Init == nullptr)4940 return nullptr;4941 return make<BracedExpr>(Index, Init, /*isArray=*/true);4942 }4943 case 'X': {4944 First += 2;4945 Node *RangeBegin = getDerived().parseExpr();4946 if (RangeBegin == nullptr)4947 return nullptr;4948 Node *RangeEnd = getDerived().parseExpr();4949 if (RangeEnd == nullptr)4950 return nullptr;4951 Node *Init = getDerived().parseBracedExpr();4952 if (Init == nullptr)4953 return nullptr;4954 return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);4955 }4956 }4957 }4958 return getDerived().parseExpr();4959}4960 4961// (not yet in the spec)4962// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>4963// ::= fR <binary-operator-name> <expression> <expression>4964// ::= fl <binary-operator-name> <expression>4965// ::= fr <binary-operator-name> <expression>4966template <typename Derived, typename Alloc>4967Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {4968 if (!consumeIf('f'))4969 return nullptr;4970 4971 bool IsLeftFold = false, HasInitializer = false;4972 switch (look()) {4973 default:4974 return nullptr;4975 case 'L':4976 IsLeftFold = true;4977 HasInitializer = true;4978 break;4979 case 'R':4980 HasInitializer = true;4981 break;4982 case 'l':4983 IsLeftFold = true;4984 break;4985 case 'r':4986 break;4987 }4988 ++First;4989 4990 const auto *Op = parseOperatorEncoding();4991 if (!Op)4992 return nullptr;4993 if (!(Op->getKind() == OperatorInfo::Binary4994 || (Op->getKind() == OperatorInfo::Member4995 && Op->getName().back() == '*')))4996 return nullptr;4997 4998 Node *Pack = getDerived().parseExpr();4999 if (Pack == nullptr)5000 return nullptr;5001 5002 Node *Init = nullptr;5003 if (HasInitializer) {5004 Init = getDerived().parseExpr();5005 if (Init == nullptr)5006 return nullptr;5007 }5008 5009 if (IsLeftFold && Init)5010 std::swap(Pack, Init);5011 5012 return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);5013}5014 5015// <expression> ::= mc <parameter type> <expr> [<offset number>] E5016//5017// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/475018template <typename Derived, typename Alloc>5019Node *5020AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(5021 Node::Prec Prec) {5022 Node *Ty = getDerived().parseType();5023 if (!Ty)5024 return nullptr;5025 Node *Expr = getDerived().parseExpr();5026 if (!Expr)5027 return nullptr;5028 std::string_view Offset = getDerived().parseNumber(true);5029 if (!consumeIf('E'))5030 return nullptr;5031 return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);5032}5033 5034// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E5035// <union-selector> ::= _ [<number>]5036//5037// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/475038template <typename Derived, typename Alloc>5039Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {5040 Node *Ty = getDerived().parseType();5041 if (!Ty)5042 return nullptr;5043 Node *Expr = getDerived().parseExpr();5044 if (!Expr)5045 return nullptr;5046 std::string_view Offset = getDerived().parseNumber(true);5047 size_t SelectorsBegin = Names.size();5048 while (consumeIf('_')) {5049 Node *Selector = make<NameType>(parseNumber());5050 if (!Selector)5051 return nullptr;5052 Names.push_back(Selector);5053 }5054 bool OnePastTheEnd = consumeIf('p');5055 if (!consumeIf('E'))5056 return nullptr;5057 return make<SubobjectExpr>(5058 Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);5059}5060 5061template <typename Derived, typename Alloc>5062Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {5063 // Within this expression, all enclosing template parameter lists are in5064 // scope.5065 ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(5066 HasIncompleteTemplateParameterTracking, true);5067 return getDerived().parseExpr();5068}5069 5070template <typename Derived, typename Alloc>5071Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {5072 NodeArray Params;5073 if (consumeIf("rQ")) {5074 // <expression> ::= rQ <bare-function-type> _ <requirement>+ E5075 size_t ParamsBegin = Names.size();5076 while (!consumeIf('_')) {5077 Node *Type = getDerived().parseType();5078 if (Type == nullptr)5079 return nullptr;5080 Names.push_back(Type);5081 }5082 Params = popTrailingNodeArray(ParamsBegin);5083 } else if (!consumeIf("rq")) {5084 // <expression> ::= rq <requirement>+ E5085 return nullptr;5086 }5087 5088 size_t ReqsBegin = Names.size();5089 do {5090 Node *Constraint = nullptr;5091 if (consumeIf('X')) {5092 // <requirement> ::= X <expression> [N] [R <type-constraint>]5093 Node *Expr = getDerived().parseExpr();5094 if (Expr == nullptr)5095 return nullptr;5096 bool Noexcept = consumeIf('N');5097 Node *TypeReq = nullptr;5098 if (consumeIf('R')) {5099 TypeReq = getDerived().parseName();5100 if (TypeReq == nullptr)5101 return nullptr;5102 }5103 Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);5104 } else if (consumeIf('T')) {5105 // <requirement> ::= T <type>5106 Node *Type = getDerived().parseType();5107 if (Type == nullptr)5108 return nullptr;5109 Constraint = make<TypeRequirement>(Type);5110 } else if (consumeIf('Q')) {5111 // <requirement> ::= Q <constraint-expression>5112 //5113 // FIXME: We use <expression> instead of <constraint-expression>. Either5114 // the requires expression is already inside a constraint expression, in5115 // which case it makes no difference, or we're in a requires-expression5116 // that might be partially-substituted, where the language behavior is5117 // not yet settled and clang mangles after substitution.5118 Node *NestedReq = getDerived().parseExpr();5119 if (NestedReq == nullptr)5120 return nullptr;5121 Constraint = make<NestedRequirement>(NestedReq);5122 }5123 if (Constraint == nullptr)5124 return nullptr;5125 Names.push_back(Constraint);5126 } while (!consumeIf('E'));5127 5128 return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));5129}5130 5131// <expression> ::= <unary operator-name> <expression>5132// ::= <binary operator-name> <expression> <expression>5133// ::= <ternary operator-name> <expression> <expression> <expression>5134// ::= cl <expression>+ E # call5135// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses5136// ::= cv <type> <expression> # conversion with one argument5137// ::= cv <type> _ <expression>* E # conversion with a different number of arguments5138// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type5139// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)5140// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type5141// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)5142// ::= [gs] dl <expression> # delete expression5143// ::= [gs] da <expression> # delete[] expression5144// ::= pp_ <expression> # prefix ++5145// ::= mm_ <expression> # prefix --5146// ::= ti <type> # typeid (type)5147// ::= te <expression> # typeid (expression)5148// ::= dc <type> <expression> # dynamic_cast<type> (expression)5149// ::= sc <type> <expression> # static_cast<type> (expression)5150// ::= cc <type> <expression> # const_cast<type> (expression)5151// ::= rc <type> <expression> # reinterpret_cast<type> (expression)5152// ::= st <type> # sizeof (a type)5153// ::= sz <expression> # sizeof (an expression)5154// ::= at <type> # alignof (a type)5155// ::= az <expression> # alignof (an expression)5156// ::= nx <expression> # noexcept (expression)5157// ::= <template-param>5158// ::= <function-param>5159// ::= dt <expression> <unresolved-name> # expr.name5160// ::= pt <expression> <unresolved-name> # expr->name5161// ::= ds <expression> <expression> # expr.*expr5162// ::= sZ <template-param> # size of a parameter pack5163// ::= sZ <function-param> # size of a function parameter pack5164// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template5165// ::= sp <expression> # pack expansion5166// ::= tw <expression> # throw expression5167// ::= tr # throw with no operand (rethrow)5168// ::= <unresolved-name> # f(p), N::f(p), ::f(p),5169// # freestanding dependent name (e.g., T::x),5170// # objectless nonstatic member reference5171// ::= fL <binary-operator-name> <expression> <expression>5172// ::= fR <binary-operator-name> <expression> <expression>5173// ::= fl <binary-operator-name> <expression>5174// ::= fr <binary-operator-name> <expression>5175// ::= <expr-primary>5176template <typename Derived, typename Alloc>5177Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {5178 bool Global = consumeIf("gs");5179 5180 const auto *Op = parseOperatorEncoding();5181 if (Op) {5182 auto Sym = Op->getSymbol();5183 switch (Op->getKind()) {5184 case OperatorInfo::Binary:5185 // Binary operator: lhs @ rhs5186 return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());5187 case OperatorInfo::Prefix:5188 // Prefix unary operator: @ expr5189 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());5190 case OperatorInfo::Postfix: {5191 // Postfix unary operator: expr @5192 if (consumeIf('_'))5193 return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());5194 Node *Ex = getDerived().parseExpr();5195 if (Ex == nullptr)5196 return nullptr;5197 return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());5198 }5199 case OperatorInfo::Array: {5200 // Array Index: lhs [ rhs ]5201 Node *Base = getDerived().parseExpr();5202 if (Base == nullptr)5203 return nullptr;5204 Node *Index = getDerived().parseExpr();5205 if (Index == nullptr)5206 return nullptr;5207 return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());5208 }5209 case OperatorInfo::Member: {5210 // Member access lhs @ rhs5211 Node *LHS = getDerived().parseExpr();5212 if (LHS == nullptr)5213 return nullptr;5214 Node *RHS = getDerived().parseExpr();5215 if (RHS == nullptr)5216 return nullptr;5217 return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());5218 }5219 case OperatorInfo::New: {5220 // New5221 // # new (expr-list) type [(init)]5222 // [gs] nw <expression>* _ <type> [pi <expression>*] E5223 // # new[] (expr-list) type [(init)]5224 // [gs] na <expression>* _ <type> [pi <expression>*] E5225 size_t Exprs = Names.size();5226 while (!consumeIf('_')) {5227 Node *Ex = getDerived().parseExpr();5228 if (Ex == nullptr)5229 return nullptr;5230 Names.push_back(Ex);5231 }5232 NodeArray ExprList = popTrailingNodeArray(Exprs);5233 Node *Ty = getDerived().parseType();5234 if (Ty == nullptr)5235 return nullptr;5236 bool HaveInits = consumeIf("pi");5237 size_t InitsBegin = Names.size();5238 while (!consumeIf('E')) {5239 if (!HaveInits)5240 return nullptr;5241 Node *Init = getDerived().parseExpr();5242 if (Init == nullptr)5243 return Init;5244 Names.push_back(Init);5245 }5246 NodeArray Inits = popTrailingNodeArray(InitsBegin);5247 return make<NewExpr>(ExprList, Ty, Inits, Global,5248 /*IsArray=*/Op->getFlag(), Op->getPrecedence());5249 }5250 case OperatorInfo::Del: {5251 // Delete5252 Node *Ex = getDerived().parseExpr();5253 if (Ex == nullptr)5254 return nullptr;5255 return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),5256 Op->getPrecedence());5257 }5258 case OperatorInfo::Call: {5259 // Function Call5260 Node *Callee = getDerived().parseExpr();5261 if (Callee == nullptr)5262 return nullptr;5263 size_t ExprsBegin = Names.size();5264 while (!consumeIf('E')) {5265 Node *E = getDerived().parseExpr();5266 if (E == nullptr)5267 return nullptr;5268 Names.push_back(E);5269 }5270 return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),5271 /*IsParen=*/Op->getFlag(), Op->getPrecedence());5272 }5273 case OperatorInfo::CCast: {5274 // C Cast: (type)expr5275 Node *Ty;5276 {5277 ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);5278 Ty = getDerived().parseType();5279 }5280 if (Ty == nullptr)5281 return nullptr;5282 5283 size_t ExprsBegin = Names.size();5284 bool IsMany = consumeIf('_');5285 while (!consumeIf('E')) {5286 Node *E = getDerived().parseExpr();5287 if (E == nullptr)5288 return E;5289 Names.push_back(E);5290 if (!IsMany)5291 break;5292 }5293 NodeArray Exprs = popTrailingNodeArray(ExprsBegin);5294 if (!IsMany && Exprs.size() != 1)5295 return nullptr;5296 return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());5297 }5298 case OperatorInfo::Conditional: {5299 // Conditional operator: expr ? expr : expr5300 Node *Cond = getDerived().parseExpr();5301 if (Cond == nullptr)5302 return nullptr;5303 Node *LHS = getDerived().parseExpr();5304 if (LHS == nullptr)5305 return nullptr;5306 Node *RHS = getDerived().parseExpr();5307 if (RHS == nullptr)5308 return nullptr;5309 return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());5310 }5311 case OperatorInfo::NamedCast: {5312 // Named cast operation, @<type>(expr)5313 Node *Ty = getDerived().parseType();5314 if (Ty == nullptr)5315 return nullptr;5316 Node *Ex = getDerived().parseExpr();5317 if (Ex == nullptr)5318 return nullptr;5319 return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());5320 }5321 case OperatorInfo::OfIdOp: {5322 // [sizeof/alignof/typeid] ( <type>|<expr> )5323 Node *Arg =5324 Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();5325 if (!Arg)5326 return nullptr;5327 return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());5328 }5329 case OperatorInfo::NameOnly: {5330 // Not valid as an expression operand.5331 return nullptr;5332 }5333 }5334 DEMANGLE_UNREACHABLE;5335 }5336 5337 if (numLeft() < 2)5338 return nullptr;5339 5340 if (look() == 'L')5341 return getDerived().parseExprPrimary();5342 if (look() == 'T')5343 return getDerived().parseTemplateParam();5344 if (look() == 'f') {5345 // Disambiguate a fold expression from a <function-param>.5346 if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))5347 return getDerived().parseFunctionParam();5348 return getDerived().parseFoldExpr();5349 }5350 if (consumeIf("il")) {5351 size_t InitsBegin = Names.size();5352 while (!consumeIf('E')) {5353 Node *E = getDerived().parseBracedExpr();5354 if (E == nullptr)5355 return nullptr;5356 Names.push_back(E);5357 }5358 return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));5359 }5360 if (consumeIf("mc"))5361 return parsePointerToMemberConversionExpr(Node::Prec::Unary);5362 if (consumeIf("nx")) {5363 Node *Ex = getDerived().parseExpr();5364 if (Ex == nullptr)5365 return Ex;5366 return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);5367 }5368 if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))5369 return parseRequiresExpr();5370 if (consumeIf("so"))5371 return parseSubobjectExpr();5372 if (consumeIf("sp")) {5373 Node *Child = getDerived().parseExpr();5374 if (Child == nullptr)5375 return nullptr;5376 return make<ParameterPackExpansion>(Child);5377 }5378 if (consumeIf("sZ")) {5379 if (look() == 'T') {5380 Node *R = getDerived().parseTemplateParam();5381 if (R == nullptr)5382 return nullptr;5383 return make<SizeofParamPackExpr>(R);5384 }5385 Node *FP = getDerived().parseFunctionParam();5386 if (FP == nullptr)5387 return nullptr;5388 return make<EnclosingExpr>("sizeof... ", FP);5389 }5390 if (consumeIf("sP")) {5391 size_t ArgsBegin = Names.size();5392 while (!consumeIf('E')) {5393 Node *Arg = getDerived().parseTemplateArg();5394 if (Arg == nullptr)5395 return nullptr;5396 Names.push_back(Arg);5397 }5398 auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));5399 if (!Pack)5400 return nullptr;5401 return make<EnclosingExpr>("sizeof... ", Pack);5402 }5403 if (consumeIf("tl")) {5404 Node *Ty = getDerived().parseType();5405 if (Ty == nullptr)5406 return nullptr;5407 size_t InitsBegin = Names.size();5408 while (!consumeIf('E')) {5409 Node *E = getDerived().parseBracedExpr();5410 if (E == nullptr)5411 return nullptr;5412 Names.push_back(E);5413 }5414 return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));5415 }5416 if (consumeIf("tr"))5417 return make<NameType>("throw");5418 if (consumeIf("tw")) {5419 Node *Ex = getDerived().parseExpr();5420 if (Ex == nullptr)5421 return nullptr;5422 return make<ThrowExpr>(Ex);5423 }5424 if (consumeIf('u')) {5425 Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);5426 if (!Name)5427 return nullptr;5428 // Special case legacy __uuidof mangling. The 't' and 'z' appear where the5429 // standard encoding expects a <template-arg>, and would be otherwise be5430 // interpreted as <type> node 'short' or 'ellipsis'. However, neither5431 // __uuidof(short) nor __uuidof(...) can actually appear, so there is no5432 // actual conflict here.5433 bool IsUUID = false;5434 Node *UUID = nullptr;5435 if (Name->getBaseName() == "__uuidof") {5436 if (consumeIf('t')) {5437 UUID = getDerived().parseType();5438 IsUUID = true;5439 } else if (consumeIf('z')) {5440 UUID = getDerived().parseExpr();5441 IsUUID = true;5442 }5443 }5444 size_t ExprsBegin = Names.size();5445 if (IsUUID) {5446 if (UUID == nullptr)5447 return nullptr;5448 Names.push_back(UUID);5449 } else {5450 while (!consumeIf('E')) {5451 Node *E = getDerived().parseTemplateArg();5452 if (E == nullptr)5453 return E;5454 Names.push_back(E);5455 }5456 }5457 return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),5458 /*IsParen=*/false, Node::Prec::Postfix);5459 }5460 5461 // Only unresolved names remain.5462 return getDerived().parseUnresolvedName(Global);5463}5464 5465// <call-offset> ::= h <nv-offset> _5466// ::= v <v-offset> _5467//5468// <nv-offset> ::= <offset number>5469// # non-virtual base override5470//5471// <v-offset> ::= <offset number> _ <virtual offset number>5472// # virtual base override, with vcall offset5473template <typename Alloc, typename Derived>5474bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {5475 // Just scan through the call offset, we never add this information into the5476 // output.5477 if (consumeIf('h'))5478 return parseNumber(true).empty() || !consumeIf('_');5479 if (consumeIf('v'))5480 return parseNumber(true).empty() || !consumeIf('_') ||5481 parseNumber(true).empty() || !consumeIf('_');5482 return true;5483}5484 5485// <special-name> ::= TV <type> # virtual table5486// ::= TT <type> # VTT structure (construction vtable index)5487// ::= TI <type> # typeinfo structure5488// ::= TS <type> # typeinfo name (null-terminated byte string)5489// ::= Tc <call-offset> <call-offset> <base encoding>5490// # base is the nominal target function of thunk5491// # first call-offset is 'this' adjustment5492// # second call-offset is result adjustment5493// ::= T <call-offset> <base encoding>5494// # base is the nominal target function of thunk5495// # Guard variable for one-time initialization5496// ::= GV <object name>5497// # No <type>5498// ::= TW <object name> # Thread-local wrapper5499// ::= TH <object name> # Thread-local initialization5500// ::= GR <object name> _ # First temporary5501// ::= GR <object name> <seq-id> _ # Subsequent temporaries5502// # construction vtable for second-in-first5503// extension ::= TC <first type> <number> _ <second type>5504// extension ::= GR <object name> # reference temporary for object5505// extension ::= GI <module name> # module global initializer5506template <typename Derived, typename Alloc>5507Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {5508 switch (look()) {5509 case 'T':5510 switch (look(1)) {5511 // TA <template-arg> # template parameter object5512 //5513 // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/635514 case 'A': {5515 First += 2;5516 Node *Arg = getDerived().parseTemplateArg();5517 if (Arg == nullptr)5518 return nullptr;5519 return make<SpecialName>("template parameter object for ", Arg);5520 }5521 // TV <type> # virtual table5522 case 'V': {5523 First += 2;5524 Node *Ty = getDerived().parseType();5525 if (Ty == nullptr)5526 return nullptr;5527 return make<SpecialName>("vtable for ", Ty);5528 }5529 // TT <type> # VTT structure (construction vtable index)5530 case 'T': {5531 First += 2;5532 Node *Ty = getDerived().parseType();5533 if (Ty == nullptr)5534 return nullptr;5535 return make<SpecialName>("VTT for ", Ty);5536 }5537 // TI <type> # typeinfo structure5538 case 'I': {5539 First += 2;5540 Node *Ty = getDerived().parseType();5541 if (Ty == nullptr)5542 return nullptr;5543 return make<SpecialName>("typeinfo for ", Ty);5544 }5545 // TS <type> # typeinfo name (null-terminated byte string)5546 case 'S': {5547 First += 2;5548 Node *Ty = getDerived().parseType();5549 if (Ty == nullptr)5550 return nullptr;5551 return make<SpecialName>("typeinfo name for ", Ty);5552 }5553 // Tc <call-offset> <call-offset> <base encoding>5554 case 'c': {5555 First += 2;5556 if (parseCallOffset() || parseCallOffset())5557 return nullptr;5558 Node *Encoding = getDerived().parseEncoding();5559 if (Encoding == nullptr)5560 return nullptr;5561 return make<SpecialName>("covariant return thunk to ", Encoding);5562 }5563 // extension ::= TC <first type> <number> _ <second type>5564 // # construction vtable for second-in-first5565 case 'C': {5566 First += 2;5567 Node *FirstType = getDerived().parseType();5568 if (FirstType == nullptr)5569 return nullptr;5570 if (parseNumber(true).empty() || !consumeIf('_'))5571 return nullptr;5572 Node *SecondType = getDerived().parseType();5573 if (SecondType == nullptr)5574 return nullptr;5575 return make<CtorVtableSpecialName>(SecondType, FirstType);5576 }5577 // TW <object name> # Thread-local wrapper5578 case 'W': {5579 First += 2;5580 Node *Name = getDerived().parseName();5581 if (Name == nullptr)5582 return nullptr;5583 return make<SpecialName>("thread-local wrapper routine for ", Name);5584 }5585 // TH <object name> # Thread-local initialization5586 case 'H': {5587 First += 2;5588 Node *Name = getDerived().parseName();5589 if (Name == nullptr)5590 return nullptr;5591 return make<SpecialName>("thread-local initialization routine for ", Name);5592 }5593 // T <call-offset> <base encoding>5594 default: {5595 ++First;5596 bool IsVirt = look() == 'v';5597 if (parseCallOffset())5598 return nullptr;5599 Node *BaseEncoding = getDerived().parseEncoding();5600 if (BaseEncoding == nullptr)5601 return nullptr;5602 if (IsVirt)5603 return make<SpecialName>("virtual thunk to ", BaseEncoding);5604 else5605 return make<SpecialName>("non-virtual thunk to ", BaseEncoding);5606 }5607 }5608 case 'G':5609 switch (look(1)) {5610 // GV <object name> # Guard variable for one-time initialization5611 case 'V': {5612 First += 2;5613 Node *Name = getDerived().parseName();5614 if (Name == nullptr)5615 return nullptr;5616 return make<SpecialName>("guard variable for ", Name);5617 }5618 // GR <object name> # reference temporary for object5619 // GR <object name> _ # First temporary5620 // GR <object name> <seq-id> _ # Subsequent temporaries5621 case 'R': {5622 First += 2;5623 Node *Name = getDerived().parseName();5624 if (Name == nullptr)5625 return nullptr;5626 size_t Count;5627 bool ParsedSeqId = !parseSeqId(&Count);5628 if (!consumeIf('_') && ParsedSeqId)5629 return nullptr;5630 return make<SpecialName>("reference temporary for ", Name);5631 }5632 // GI <module-name> v5633 case 'I': {5634 First += 2;5635 ModuleName *Module = nullptr;5636 if (getDerived().parseModuleNameOpt(Module))5637 return nullptr;5638 if (Module == nullptr)5639 return nullptr;5640 return make<SpecialName>("initializer for module ", Module);5641 }5642 }5643 }5644 return nullptr;5645}5646 5647// <encoding> ::= <function name> <bare-function-type>5648// [`Q` <requires-clause expr>]5649// ::= <data name>5650// ::= <special-name>5651template <typename Derived, typename Alloc>5652Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {5653 // The template parameters of an encoding are unrelated to those of the5654 // enclosing context.5655 SaveTemplateParams SaveTemplateParamsScope(this);5656 5657 if (look() == 'G' || look() == 'T')5658 return getDerived().parseSpecialName();5659 5660 auto IsEndOfEncoding = [&] {5661 // The set of chars that can potentially follow an <encoding> (none of which5662 // can start a <type>). Enumerating these allows us to avoid speculative5663 // parsing.5664 return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';5665 };5666 5667 NameState NameInfo(this);5668 Node *Name = getDerived().parseName(&NameInfo);5669 if (Name == nullptr)5670 return nullptr;5671 5672 if (resolveForwardTemplateRefs(NameInfo))5673 return nullptr;5674 5675 if (IsEndOfEncoding())5676 return Name;5677 5678 // ParseParams may be false at the top level only, when called from parse().5679 // For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be5680 // false when demangling 3fooILZ3BarEET_f but is always true when demangling5681 // 3Bar.5682 if (!ParseParams) {5683 while (consume())5684 ;5685 return Name;5686 }5687 5688 Node *Attrs = nullptr;5689 if (consumeIf("Ua9enable_ifI")) {5690 size_t BeforeArgs = Names.size();5691 while (!consumeIf('E')) {5692 Node *Arg = getDerived().parseTemplateArg();5693 if (Arg == nullptr)5694 return nullptr;5695 Names.push_back(Arg);5696 }5697 Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));5698 if (!Attrs)5699 return nullptr;5700 }5701 5702 Node *ReturnType = nullptr;5703 if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {5704 ReturnType = getDerived().parseType();5705 if (ReturnType == nullptr)5706 return nullptr;5707 }5708 5709 NodeArray Params;5710 if (!consumeIf('v')) {5711 size_t ParamsBegin = Names.size();5712 do {5713 Node *Ty = getDerived().parseType();5714 if (Ty == nullptr)5715 return nullptr;5716 5717 const bool IsFirstParam = ParamsBegin == Names.size();5718 if (NameInfo.HasExplicitObjectParameter && IsFirstParam)5719 Ty = make<ExplicitObjectParameter>(Ty);5720 5721 if (Ty == nullptr)5722 return nullptr;5723 5724 Names.push_back(Ty);5725 } while (!IsEndOfEncoding() && look() != 'Q');5726 Params = popTrailingNodeArray(ParamsBegin);5727 }5728 5729 Node *Requires = nullptr;5730 if (consumeIf('Q')) {5731 Requires = getDerived().parseConstraintExpr();5732 if (!Requires)5733 return nullptr;5734 }5735 5736 return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,5737 NameInfo.CVQualifiers,5738 NameInfo.ReferenceQualifier);5739}5740 5741template <class Float>5742struct FloatData;5743 5744template <>5745struct FloatData<float>5746{5747 static const size_t mangled_size = 8;5748 static const size_t max_demangled_size = 24;5749 static constexpr const char* spec = "%af";5750};5751 5752template <>5753struct FloatData<double>5754{5755 static const size_t mangled_size = 16;5756 static const size_t max_demangled_size = 32;5757 static constexpr const char* spec = "%a";5758};5759 5760template <>5761struct FloatData<long double>5762{5763#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 1065764 static const size_t mangled_size = 32;5765#elif __LDBL_MANT_DIG__ == 53 || defined(_MSC_VER)5766 // MSVC doesn't define __LDBL_MANT_DIG__, but it has long double equal to5767 // regular double on all current architectures.5768 static const size_t mangled_size = 16;5769#elif __LDBL_MANT_DIG__ == 645770 static const size_t mangled_size = 20;5771#else5772#error Unknown size for __LDBL_MANT_DIG__5773#endif5774 // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.5775 // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.5776 // Negatives are one character longer than positives.5777 // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the5778 // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.5779 static const size_t max_demangled_size = 42;5780 static constexpr const char *spec = "%LaL";5781};5782 5783template <typename Alloc, typename Derived>5784template <class Float>5785Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {5786 const size_t N = FloatData<Float>::mangled_size;5787 if (numLeft() <= N)5788 return nullptr;5789 std::string_view Data(First, N);5790 for (char C : Data)5791 if (!(C >= '0' && C <= '9') && !(C >= 'a' && C <= 'f'))5792 return nullptr;5793 First += N;5794 if (!consumeIf('E'))5795 return nullptr;5796 return make<FloatLiteralImpl<Float>>(Data);5797}5798 5799// <seq-id> ::= <0-9A-Z>+5800template <typename Alloc, typename Derived>5801bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {5802 if (!(look() >= '0' && look() <= '9') &&5803 !(look() >= 'A' && look() <= 'Z'))5804 return true;5805 5806 size_t Id = 0;5807 while (true) {5808 if (look() >= '0' && look() <= '9') {5809 Id *= 36;5810 Id += static_cast<size_t>(look() - '0');5811 } else if (look() >= 'A' && look() <= 'Z') {5812 Id *= 36;5813 Id += static_cast<size_t>(look() - 'A') + 10;5814 } else {5815 *Out = Id;5816 return false;5817 }5818 ++First;5819 }5820}5821 5822// <substitution> ::= S <seq-id> _5823// ::= S_5824// <substitution> ::= Sa # ::std::allocator5825// <substitution> ::= Sb # ::std::basic_string5826// <substitution> ::= Ss # ::std::basic_string < char,5827// ::std::char_traits<char>,5828// ::std::allocator<char> >5829// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >5830// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >5831// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >5832// The St case is handled specially in parseNestedName.5833template <typename Derived, typename Alloc>5834Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {5835 if (!consumeIf('S'))5836 return nullptr;5837 5838 if (look() >= 'a' && look() <= 'z') {5839 SpecialSubKind Kind;5840 switch (look()) {5841 case 'a':5842 Kind = SpecialSubKind::allocator;5843 break;5844 case 'b':5845 Kind = SpecialSubKind::basic_string;5846 break;5847 case 'd':5848 Kind = SpecialSubKind::iostream;5849 break;5850 case 'i':5851 Kind = SpecialSubKind::istream;5852 break;5853 case 'o':5854 Kind = SpecialSubKind::ostream;5855 break;5856 case 's':5857 Kind = SpecialSubKind::string;5858 break;5859 default:5860 return nullptr;5861 }5862 ++First;5863 auto *SpecialSub = make<SpecialSubstitution>(Kind);5864 if (!SpecialSub)5865 return nullptr;5866 5867 // Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>5868 // has ABI tags, the tags are appended to the substitution; the result is a5869 // substitutable component.5870 Node *WithTags = getDerived().parseAbiTags(SpecialSub);5871 if (WithTags != SpecialSub) {5872 Subs.push_back(WithTags);5873 SpecialSub = WithTags;5874 }5875 return SpecialSub;5876 }5877 5878 // ::= S_5879 if (consumeIf('_')) {5880 if (Subs.empty())5881 return nullptr;5882 return Subs[0];5883 }5884 5885 // ::= S <seq-id> _5886 size_t Index = 0;5887 if (parseSeqId(&Index))5888 return nullptr;5889 ++Index;5890 if (!consumeIf('_') || Index >= Subs.size())5891 return nullptr;5892 return Subs[Index];5893}5894 5895// <template-param> ::= T_ # first template parameter5896// ::= T <parameter-2 non-negative number> _5897// ::= TL <level-1> __5898// ::= TL <level-1> _ <parameter-2 non-negative number> _5899template <typename Derived, typename Alloc>5900Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {5901 const char *Begin = First;5902 if (!consumeIf('T'))5903 return nullptr;5904 5905 size_t Level = 0;5906 if (consumeIf('L')) {5907 if (parsePositiveInteger(&Level))5908 return nullptr;5909 ++Level;5910 if (!consumeIf('_'))5911 return nullptr;5912 }5913 5914 size_t Index = 0;5915 if (!consumeIf('_')) {5916 if (parsePositiveInteger(&Index))5917 return nullptr;5918 ++Index;5919 if (!consumeIf('_'))5920 return nullptr;5921 }5922 5923 // We don't track enclosing template parameter levels well enough to reliably5924 // substitute them all within a <constraint-expression>, so print the5925 // parameter numbering instead for now.5926 // TODO: Track all enclosing template parameters and substitute them here.5927 if (HasIncompleteTemplateParameterTracking) {5928 return make<NameType>(std::string_view(Begin, First - 1 - Begin));5929 }5930 5931 // If we're in a context where this <template-param> refers to a5932 // <template-arg> further ahead in the mangled name (currently just conversion5933 // operator types), then we should only look it up in the right context.5934 // This can only happen at the outermost level.5935 if (PermitForwardTemplateReferences && Level == 0) {5936 Node *ForwardRef = make<ForwardTemplateReference>(Index);5937 if (!ForwardRef)5938 return nullptr;5939 DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,5940 "");5941 ForwardTemplateRefs.push_back(5942 static_cast<ForwardTemplateReference *>(ForwardRef));5943 return ForwardRef;5944 }5945 5946 if (Level >= TemplateParams.size() || !TemplateParams[Level] ||5947 Index >= TemplateParams[Level]->size()) {5948 // Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter5949 // list are mangled as the corresponding artificial template type parameter.5950 if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {5951 // This will be popped by the ScopedTemplateParamList in5952 // parseUnnamedTypeName.5953 if (Level == TemplateParams.size())5954 TemplateParams.push_back(nullptr);5955 return make<NameType>("auto");5956 }5957 5958 return nullptr;5959 }5960 5961 return (*TemplateParams[Level])[Index];5962}5963 5964// <template-param-decl> ::= Ty # type parameter5965// ::= Tk <concept name> [<template-args>] # constrained type parameter5966// ::= Tn <type> # non-type parameter5967// ::= Tt <template-param-decl>* E # template parameter5968// ::= Tp <template-param-decl> # parameter pack5969template <typename Derived, typename Alloc>5970Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(5971 TemplateParamList *Params) {5972 auto InventTemplateParamName = [&](TemplateParamKind Kind) {5973 unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;5974 Node *N = make<SyntheticTemplateParamName>(Kind, Index);5975 if (N && Params)5976 Params->push_back(N);5977 return N;5978 };5979 5980 if (consumeIf("Ty")) {5981 Node *Name = InventTemplateParamName(TemplateParamKind::Type);5982 if (!Name)5983 return nullptr;5984 return make<TypeTemplateParamDecl>(Name);5985 }5986 5987 if (consumeIf("Tk")) {5988 // We don't track enclosing template parameter levels well enough to5989 // reliably demangle template parameter substitutions, so print an arbitrary5990 // string in place of a parameter for now.5991 // TODO: Track all enclosing template parameters and demangle substitutions.5992 ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(5993 HasIncompleteTemplateParameterTracking, true);5994 Node *Constraint = getDerived().parseName();5995 if (!Constraint)5996 return nullptr;5997 Node *Name = InventTemplateParamName(TemplateParamKind::Type);5998 if (!Name)5999 return nullptr;6000 return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);6001 }6002 6003 if (consumeIf("Tn")) {6004 Node *Name = InventTemplateParamName(TemplateParamKind::NonType);6005 if (!Name)6006 return nullptr;6007 Node *Type = parseType();6008 if (!Type)6009 return nullptr;6010 return make<NonTypeTemplateParamDecl>(Name, Type);6011 }6012 6013 if (consumeIf("Tt")) {6014 Node *Name = InventTemplateParamName(TemplateParamKind::Template);6015 if (!Name)6016 return nullptr;6017 size_t ParamsBegin = Names.size();6018 ScopedTemplateParamList TemplateTemplateParamParams(this);6019 Node *Requires = nullptr;6020 while (!consumeIf('E')) {6021 Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());6022 if (!P)6023 return nullptr;6024 Names.push_back(P);6025 if (consumeIf('Q')) {6026 Requires = getDerived().parseConstraintExpr();6027 if (Requires == nullptr || !consumeIf('E'))6028 return nullptr;6029 break;6030 }6031 }6032 NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);6033 return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);6034 }6035 6036 if (consumeIf("Tp")) {6037 Node *P = parseTemplateParamDecl(Params);6038 if (!P)6039 return nullptr;6040 return make<TemplateParamPackDecl>(P);6041 }6042 6043 return nullptr;6044}6045 6046// <template-arg> ::= <type> # type or template6047// ::= X <expression> E # expression6048// ::= <expr-primary> # simple expressions6049// ::= J <template-arg>* E # argument pack6050// ::= LZ <encoding> E # extension6051// ::= <template-param-decl> <template-arg>6052template <typename Derived, typename Alloc>6053Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {6054 switch (look()) {6055 case 'X': {6056 ++First;6057 Node *Arg = getDerived().parseExpr();6058 if (Arg == nullptr || !consumeIf('E'))6059 return nullptr;6060 return Arg;6061 }6062 case 'J': {6063 ++First;6064 size_t ArgsBegin = Names.size();6065 while (!consumeIf('E')) {6066 Node *Arg = getDerived().parseTemplateArg();6067 if (Arg == nullptr)6068 return nullptr;6069 Names.push_back(Arg);6070 }6071 NodeArray Args = popTrailingNodeArray(ArgsBegin);6072 return make<TemplateArgumentPack>(Args);6073 }6074 case 'L': {6075 // ::= LZ <encoding> E # extension6076 if (look(1) == 'Z') {6077 First += 2;6078 Node *Arg = getDerived().parseEncoding();6079 if (Arg == nullptr || !consumeIf('E'))6080 return nullptr;6081 return Arg;6082 }6083 // ::= <expr-primary> # simple expressions6084 return getDerived().parseExprPrimary();6085 }6086 case 'T': {6087 // Either <template-param> or a <template-param-decl> <template-arg>.6088 if (!getDerived().isTemplateParamDecl())6089 return getDerived().parseType();6090 Node *Param = getDerived().parseTemplateParamDecl(nullptr);6091 if (!Param)6092 return nullptr;6093 Node *Arg = getDerived().parseTemplateArg();6094 if (!Arg)6095 return nullptr;6096 return make<TemplateParamQualifiedArg>(Param, Arg);6097 }6098 default:6099 return getDerived().parseType();6100 }6101}6102 6103// <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E6104// extension, the abi says <template-arg>+6105template <typename Derived, typename Alloc>6106Node *6107AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {6108 if (!consumeIf('I'))6109 return nullptr;6110 6111 // <template-params> refer to the innermost <template-args>. Clear out any6112 // outer args that we may have inserted into TemplateParams.6113 if (TagTemplates) {6114 TemplateParams.clear();6115 TemplateParams.push_back(&OuterTemplateParams);6116 OuterTemplateParams.clear();6117 }6118 6119 size_t ArgsBegin = Names.size();6120 Node *Requires = nullptr;6121 while (!consumeIf('E')) {6122 if (TagTemplates) {6123 Node *Arg = getDerived().parseTemplateArg();6124 if (Arg == nullptr)6125 return nullptr;6126 Names.push_back(Arg);6127 Node *TableEntry = Arg;6128 if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {6129 TableEntry =6130 static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();6131 }6132 if (Arg->getKind() == Node::KTemplateArgumentPack) {6133 TableEntry = make<ParameterPack>(6134 static_cast<TemplateArgumentPack*>(TableEntry)->getElements());6135 if (!TableEntry)6136 return nullptr;6137 }6138 OuterTemplateParams.push_back(TableEntry);6139 } else {6140 Node *Arg = getDerived().parseTemplateArg();6141 if (Arg == nullptr)6142 return nullptr;6143 Names.push_back(Arg);6144 }6145 if (consumeIf('Q')) {6146 Requires = getDerived().parseConstraintExpr();6147 if (!Requires || !consumeIf('E'))6148 return nullptr;6149 break;6150 }6151 }6152 return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);6153}6154 6155// <mangled-name> ::= _Z <encoding>6156// ::= <type>6157// extension ::= ___Z <encoding> _block_invoke6158// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+6159// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+6160template <typename Derived, typename Alloc>6161Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {6162 if (consumeIf("_Z") || consumeIf("__Z")) {6163 Node *Encoding = getDerived().parseEncoding(ParseParams);6164 if (Encoding == nullptr)6165 return nullptr;6166 if (look() == '.') {6167 Encoding =6168 make<DotSuffix>(Encoding, std::string_view(First, Last - First));6169 First = Last;6170 }6171 if (numLeft() != 0)6172 return nullptr;6173 return Encoding;6174 }6175 6176 if (consumeIf("___Z") || consumeIf("____Z")) {6177 Node *Encoding = getDerived().parseEncoding(ParseParams);6178 if (Encoding == nullptr || !consumeIf("_block_invoke"))6179 return nullptr;6180 bool RequireNumber = consumeIf('_');6181 if (parseNumber().empty() && RequireNumber)6182 return nullptr;6183 if (look() == '.')6184 First = Last;6185 if (numLeft() != 0)6186 return nullptr;6187 return make<SpecialName>("invocation function for block in ", Encoding);6188 }6189 6190 Node *Ty = getDerived().parseType();6191 if (numLeft() != 0)6192 return nullptr;6193 return Ty;6194}6195 6196template <typename Alloc>6197struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {6198 using AbstractManglingParser<ManglingParser<Alloc>,6199 Alloc>::AbstractManglingParser;6200};6201 6202inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); }6203 6204inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); }6205 6206DEMANGLE_NAMESPACE_END6207 6208#if defined(__clang__)6209#pragma clang diagnostic pop6210#endif6211 6212#endif // DEMANGLE_ITANIUMDEMANGLE_H6213