Path: blob/main/system/lib/libcxxabi/src/demangle/ItaniumDemangle.h
6174 views
//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Generic itanium demangler library.9// There are two copies of this file in the source tree. The one under10// libcxxabi is the original and the one under llvm is the copy. Use11// cp-to-llvm.sh to update the copy. See README.txt for more details.12//13//===----------------------------------------------------------------------===//1415#ifndef DEMANGLE_ITANIUMDEMANGLE_H16#define DEMANGLE_ITANIUMDEMANGLE_H1718#include "DemangleConfig.h"19#include "StringViewExtras.h"20#include "Utility.h"21#include <algorithm>22#include <cctype>23#include <cstdint>24#include <cstdio>25#include <cstdlib>26#include <cstring>27#include <limits>28#include <new>29#include <string_view>30#include <type_traits>31#include <utility>3233#if defined(__clang__)34#pragma clang diagnostic push35#pragma clang diagnostic ignored "-Wunused-template"36#endif3738DEMANGLE_NAMESPACE_BEGIN3940template <class T, size_t N> class PODSmallVector {41static_assert(std::is_trivially_copyable<T>::value,42"T is required to be a trivially copyable type");43static_assert(std::is_trivially_default_constructible<T>::value,44"T is required to be trivially default constructible");45T *First = nullptr;46T *Last = nullptr;47T *Cap = nullptr;48T Inline[N] = {};4950bool isInline() const { return First == Inline; }5152void clearInline() {53First = Inline;54Last = Inline;55Cap = Inline + N;56}5758void reserve(size_t NewCap) {59size_t S = size();60if (isInline()) {61auto *Tmp = static_cast<T *>(std::malloc(NewCap * sizeof(T)));62if (Tmp == nullptr)63std::abort();64std::copy(First, Last, Tmp);65First = Tmp;66} else {67First = static_cast<T *>(std::realloc(First, NewCap * sizeof(T)));68if (First == nullptr)69std::abort();70}71Last = First + S;72Cap = First + NewCap;73}7475public:76PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}7778PODSmallVector(const PODSmallVector &) = delete;79PODSmallVector &operator=(const PODSmallVector &) = delete;8081PODSmallVector(PODSmallVector &&Other) : PODSmallVector() {82if (Other.isInline()) {83std::copy(Other.begin(), Other.end(), First);84Last = First + Other.size();85Other.clear();86return;87}8889First = Other.First;90Last = Other.Last;91Cap = Other.Cap;92Other.clearInline();93}9495PODSmallVector &operator=(PODSmallVector &&Other) {96if (Other.isInline()) {97if (!isInline()) {98std::free(First);99clearInline();100}101std::copy(Other.begin(), Other.end(), First);102Last = First + Other.size();103Other.clear();104return *this;105}106107if (isInline()) {108First = Other.First;109Last = Other.Last;110Cap = Other.Cap;111Other.clearInline();112return *this;113}114115std::swap(First, Other.First);116std::swap(Last, Other.Last);117std::swap(Cap, Other.Cap);118Other.clear();119return *this;120}121122// NOLINTNEXTLINE(readability-identifier-naming)123void push_back(const T &Elem) {124if (Last == Cap)125reserve(size() * 2);126*Last++ = Elem;127}128129// NOLINTNEXTLINE(readability-identifier-naming)130void pop_back() {131DEMANGLE_ASSERT(Last != First, "Popping empty vector!");132--Last;133}134135void shrinkToSize(size_t Index) {136DEMANGLE_ASSERT(Index <= size(), "shrinkToSize() can't expand!");137Last = First + Index;138}139140T *begin() { return First; }141T *end() { return Last; }142143bool empty() const { return First == Last; }144size_t size() const { return static_cast<size_t>(Last - First); }145T &back() {146DEMANGLE_ASSERT(Last != First, "Calling back() on empty vector!");147return *(Last - 1);148}149T &operator[](size_t Index) {150DEMANGLE_ASSERT(Index < size(), "Invalid access!");151return *(begin() + Index);152}153void clear() { Last = First; }154155~PODSmallVector() {156if (!isInline())157std::free(First);158}159};160161class NodeArray;162163// Base class of all AST nodes. The AST is built by the parser, then is164// traversed by the printLeft/Right functions to produce a demangled string.165class Node {166public:167enum Kind : uint8_t {168#define NODE(NodeKind) K##NodeKind,169#include "ItaniumNodes.def"170};171172/// Three-way bool to track a cached value. Unknown is possible if this node173/// has an unexpanded parameter pack below it that may affect this cache.174enum class Cache : uint8_t { Yes, No, Unknown, };175176/// Operator precedence for expression nodes. Used to determine required177/// parens in expression emission.178enum class Prec : uint8_t {179Primary,180Postfix,181Unary,182Cast,183PtrMem,184Multiplicative,185Additive,186Shift,187Spaceship,188Relational,189Equality,190And,191Xor,192Ior,193AndIf,194OrIf,195Conditional,196Assign,197Comma,198Default,199};200201private:202Kind K;203204Prec Precedence : 6;205206protected:207/// Tracks if this node has a component on its right side, in which case we208/// need to call printRight.209Cache RHSComponentCache : 2;210211/// Track if this node is a (possibly qualified) array type. This can affect212/// how we format the output string.213Cache ArrayCache : 2;214215/// Track if this node is a (possibly qualified) function type. This can216/// affect how we format the output string.217Cache FunctionCache : 2;218219public:220Node(Kind K_, Prec Precedence_ = Prec::Primary,221Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No,222Cache FunctionCache_ = Cache::No)223: K(K_), Precedence(Precedence_), RHSComponentCache(RHSComponentCache_),224ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {}225Node(Kind K_, Cache RHSComponentCache_, Cache ArrayCache_ = Cache::No,226Cache FunctionCache_ = Cache::No)227: Node(K_, Prec::Primary, RHSComponentCache_, ArrayCache_,228FunctionCache_) {}229230/// Visit the most-derived object corresponding to this object.231template<typename Fn> void visit(Fn F) const;232233// The following function is provided by all derived classes:234//235// Call F with arguments that, when passed to the constructor of this node,236// would construct an equivalent node.237//template<typename Fn> void match(Fn F) const;238239bool hasRHSComponent(OutputBuffer &OB) const {240if (RHSComponentCache != Cache::Unknown)241return RHSComponentCache == Cache::Yes;242return hasRHSComponentSlow(OB);243}244245bool hasArray(OutputBuffer &OB) const {246if (ArrayCache != Cache::Unknown)247return ArrayCache == Cache::Yes;248return hasArraySlow(OB);249}250251bool hasFunction(OutputBuffer &OB) const {252if (FunctionCache != Cache::Unknown)253return FunctionCache == Cache::Yes;254return hasFunctionSlow(OB);255}256257Kind getKind() const { return K; }258259Prec getPrecedence() const { return Precedence; }260Cache getRHSComponentCache() const { return RHSComponentCache; }261Cache getArrayCache() const { return ArrayCache; }262Cache getFunctionCache() const { return FunctionCache; }263264virtual bool hasRHSComponentSlow(OutputBuffer &) const { return false; }265virtual bool hasArraySlow(OutputBuffer &) const { return false; }266virtual bool hasFunctionSlow(OutputBuffer &) const { return false; }267268// Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to269// get at a node that actually represents some concrete syntax.270virtual const Node *getSyntaxNode(OutputBuffer &) const { return this; }271272// Print this node as an expression operand, surrounding it in parentheses if273// its precedence is [Strictly] weaker than P.274void printAsOperand(OutputBuffer &OB, Prec P = Prec::Default,275bool StrictlyWorse = false) const {276bool Paren =277unsigned(getPrecedence()) >= unsigned(P) + unsigned(StrictlyWorse);278if (Paren)279OB.printOpen();280print(OB);281if (Paren)282OB.printClose();283}284285void print(OutputBuffer &OB) const {286OB.printLeft(*this);287if (RHSComponentCache != Cache::No)288OB.printRight(*this);289}290291// Print an initializer list of this type. Returns true if we printed a custom292// representation, false if nothing has been printed and the default293// representation should be used.294virtual bool printInitListAsType(OutputBuffer &, const NodeArray &) const {295return false;296}297298virtual std::string_view getBaseName() const { return {}; }299300// Silence compiler warnings, this dtor will never be called.301virtual ~Node() = default;302303#ifndef NDEBUG304DEMANGLE_DUMP_METHOD void dump() const;305#endif306307private:308friend class OutputBuffer;309310// Print the "left" side of this Node into OutputBuffer.311//312// Note, should only be called from OutputBuffer implementations.313// Call \ref OutputBuffer::printLeft instead.314virtual void printLeft(OutputBuffer &) const = 0;315316// Print the "right". This distinction is necessary to represent C++ types317// that appear on the RHS of their subtype, such as arrays or functions.318// Since most types don't have such a component, provide a default319// implementation.320//321// Note, should only be called from OutputBuffer implementations.322// Call \ref OutputBuffer::printRight instead.323virtual void printRight(OutputBuffer &) const {}324};325326class NodeArray {327Node **Elements;328size_t NumElements;329330public:331NodeArray() : Elements(nullptr), NumElements(0) {}332NodeArray(Node **Elements_, size_t NumElements_)333: Elements(Elements_), NumElements(NumElements_) {}334335bool empty() const { return NumElements == 0; }336size_t size() const { return NumElements; }337338Node **begin() const { return Elements; }339Node **end() const { return Elements + NumElements; }340341Node *operator[](size_t Idx) const { return Elements[Idx]; }342343void printWithComma(OutputBuffer &OB) const {344bool FirstElement = true;345for (size_t Idx = 0; Idx != NumElements; ++Idx) {346size_t BeforeComma = OB.getCurrentPosition();347if (!FirstElement)348OB += ", ";349size_t AfterComma = OB.getCurrentPosition();350Elements[Idx]->printAsOperand(OB, Node::Prec::Comma);351352// Elements[Idx] is an empty parameter pack expansion, we should erase the353// comma we just printed.354if (AfterComma == OB.getCurrentPosition()) {355OB.setCurrentPosition(BeforeComma);356continue;357}358359FirstElement = false;360}361}362363// Print an array of integer literals as a string literal. Returns whether we364// could do so.365bool printAsString(OutputBuffer &OB) const;366};367368struct NodeArrayNode : Node {369NodeArray Array;370NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}371372template<typename Fn> void match(Fn F) const { F(Array); }373374void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); }375};376377class DotSuffix final : public Node {378const Node *Prefix;379const std::string_view Suffix;380381public:382DotSuffix(const Node *Prefix_, std::string_view Suffix_)383: Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}384385template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }386387void printLeft(OutputBuffer &OB) const override {388Prefix->print(OB);389OB += " (";390OB += Suffix;391OB += ")";392}393};394395class VendorExtQualType final : public Node {396const Node *Ty;397std::string_view Ext;398const Node *TA;399400public:401VendorExtQualType(const Node *Ty_, std::string_view Ext_, const Node *TA_)402: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_), TA(TA_) {}403404const Node *getTy() const { return Ty; }405std::string_view getExt() const { return Ext; }406const Node *getTA() const { return TA; }407408template <typename Fn> void match(Fn F) const { F(Ty, Ext, TA); }409410void printLeft(OutputBuffer &OB) const override {411Ty->print(OB);412OB += " ";413OB += Ext;414if (TA != nullptr)415TA->print(OB);416}417};418419enum FunctionRefQual : unsigned char {420FrefQualNone,421FrefQualLValue,422FrefQualRValue,423};424425enum Qualifiers {426QualNone = 0,427QualConst = 0x1,428QualVolatile = 0x2,429QualRestrict = 0x4,430};431432inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {433return Q1 = static_cast<Qualifiers>(Q1 | Q2);434}435436class QualType final : public Node {437protected:438const Qualifiers Quals;439const Node *Child;440441void printQuals(OutputBuffer &OB) const {442if (Quals & QualConst)443OB += " const";444if (Quals & QualVolatile)445OB += " volatile";446if (Quals & QualRestrict)447OB += " restrict";448}449450public:451QualType(const Node *Child_, Qualifiers Quals_)452: Node(KQualType, Child_->getRHSComponentCache(), Child_->getArrayCache(),453Child_->getFunctionCache()),454Quals(Quals_), Child(Child_) {}455456Qualifiers getQuals() const { return Quals; }457const Node *getChild() const { return Child; }458459template<typename Fn> void match(Fn F) const { F(Child, Quals); }460461bool hasRHSComponentSlow(OutputBuffer &OB) const override {462return Child->hasRHSComponent(OB);463}464bool hasArraySlow(OutputBuffer &OB) const override {465return Child->hasArray(OB);466}467bool hasFunctionSlow(OutputBuffer &OB) const override {468return Child->hasFunction(OB);469}470471void printLeft(OutputBuffer &OB) const override {472OB.printLeft(*Child);473printQuals(OB);474}475476void printRight(OutputBuffer &OB) const override { OB.printRight(*Child); }477};478479class ConversionOperatorType final : public Node {480const Node *Ty;481482public:483ConversionOperatorType(const Node *Ty_)484: Node(KConversionOperatorType), Ty(Ty_) {}485486template<typename Fn> void match(Fn F) const { F(Ty); }487488void printLeft(OutputBuffer &OB) const override {489OB += "operator ";490Ty->print(OB);491}492};493494class PostfixQualifiedType final : public Node {495const Node *Ty;496const std::string_view Postfix;497498public:499PostfixQualifiedType(const Node *Ty_, std::string_view Postfix_)500: Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}501502template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }503504void printLeft(OutputBuffer &OB) const override {505OB.printLeft(*Ty);506OB += Postfix;507}508};509510class NameType final : public Node {511const std::string_view Name;512513public:514NameType(std::string_view Name_) : Node(KNameType), Name(Name_) {}515516template<typename Fn> void match(Fn F) const { F(Name); }517518std::string_view getName() const { return Name; }519std::string_view getBaseName() const override { return Name; }520521void printLeft(OutputBuffer &OB) const override { OB += Name; }522};523524class BitIntType final : public Node {525const Node *Size;526bool Signed;527528public:529BitIntType(const Node *Size_, bool Signed_)530: Node(KBitIntType), Size(Size_), Signed(Signed_) {}531532template <typename Fn> void match(Fn F) const { F(Size, Signed); }533534void printLeft(OutputBuffer &OB) const override {535if (!Signed)536OB += "unsigned ";537OB += "_BitInt";538OB.printOpen();539Size->printAsOperand(OB);540OB.printClose();541}542};543544class ElaboratedTypeSpefType : public Node {545std::string_view Kind;546Node *Child;547public:548ElaboratedTypeSpefType(std::string_view Kind_, Node *Child_)549: Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}550551template<typename Fn> void match(Fn F) const { F(Kind, Child); }552553void printLeft(OutputBuffer &OB) const override {554OB += Kind;555OB += ' ';556Child->print(OB);557}558};559560class TransformedType : public Node {561std::string_view Transform;562Node *BaseType;563public:564TransformedType(std::string_view Transform_, Node *BaseType_)565: Node(KTransformedType), Transform(Transform_), BaseType(BaseType_) {}566567template<typename Fn> void match(Fn F) const { F(Transform, BaseType); }568569void printLeft(OutputBuffer &OB) const override {570OB += Transform;571OB += '(';572BaseType->print(OB);573OB += ')';574}575};576577struct AbiTagAttr : Node {578Node *Base;579std::string_view Tag;580581AbiTagAttr(Node *Base_, std::string_view Tag_)582: Node(KAbiTagAttr, Base_->getRHSComponentCache(), Base_->getArrayCache(),583Base_->getFunctionCache()),584Base(Base_), Tag(Tag_) {}585586template<typename Fn> void match(Fn F) const { F(Base, Tag); }587588std::string_view getBaseName() const override { return Base->getBaseName(); }589590void printLeft(OutputBuffer &OB) const override {591OB.printLeft(*Base);592OB += "[abi:";593OB += Tag;594OB += "]";595}596};597598class EnableIfAttr : public Node {599NodeArray Conditions;600public:601EnableIfAttr(NodeArray Conditions_)602: Node(KEnableIfAttr), Conditions(Conditions_) {}603604template<typename Fn> void match(Fn F) const { F(Conditions); }605606void printLeft(OutputBuffer &OB) const override {607OB += " [enable_if:";608Conditions.printWithComma(OB);609OB += ']';610}611};612613class ObjCProtoName : public Node {614const Node *Ty;615std::string_view Protocol;616617public:618ObjCProtoName(const Node *Ty_, std::string_view Protocol_)619: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}620621template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }622623bool isObjCObject() const {624return Ty->getKind() == KNameType &&625static_cast<const NameType *>(Ty)->getName() == "objc_object";626}627628std::string_view getProtocol() const { return Protocol; }629630void printLeft(OutputBuffer &OB) const override {631Ty->print(OB);632OB += "<";633OB += Protocol;634OB += ">";635}636};637638class PointerType final : public Node {639const Node *Pointee;640641public:642PointerType(const Node *Pointee_)643: Node(KPointerType, Pointee_->getRHSComponentCache()),644Pointee(Pointee_) {}645646const Node *getPointee() const { return Pointee; }647648template<typename Fn> void match(Fn F) const { F(Pointee); }649650bool hasRHSComponentSlow(OutputBuffer &OB) const override {651return Pointee->hasRHSComponent(OB);652}653654void printLeft(OutputBuffer &OB) const override {655// We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.656if (Pointee->getKind() != KObjCProtoName ||657!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {658OB.printLeft(*Pointee);659if (Pointee->hasArray(OB))660OB += " ";661if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))662OB += "(";663OB += "*";664} else {665const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);666OB += "id<";667OB += objcProto->getProtocol();668OB += ">";669}670}671672void printRight(OutputBuffer &OB) const override {673if (Pointee->getKind() != KObjCProtoName ||674!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {675if (Pointee->hasArray(OB) || Pointee->hasFunction(OB))676OB += ")";677OB.printRight(*Pointee);678}679}680};681682enum class ReferenceKind {683LValue,684RValue,685};686687// Represents either a LValue or an RValue reference type.688class ReferenceType : public Node {689const Node *Pointee;690ReferenceKind RK;691692mutable bool Printing = false;693694// Dig through any refs to refs, collapsing the ReferenceTypes as we go. The695// rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any696// other combination collapses to a lvalue ref.697//698// A combination of a TemplateForwardReference and a back-ref Substitution699// from an ill-formed string may have created a cycle; use cycle detection to700// avoid looping forever.701std::pair<ReferenceKind, const Node *> collapse(OutputBuffer &OB) const {702auto SoFar = std::make_pair(RK, Pointee);703// Track the chain of nodes for the Floyd's 'tortoise and hare'704// cycle-detection algorithm, since getSyntaxNode(S) is impure705PODSmallVector<const Node *, 8> Prev;706for (;;) {707const Node *SN = SoFar.second->getSyntaxNode(OB);708if (SN->getKind() != KReferenceType)709break;710auto *RT = static_cast<const ReferenceType *>(SN);711SoFar.second = RT->Pointee;712SoFar.first = std::min(SoFar.first, RT->RK);713714// The middle of Prev is the 'slow' pointer moving at half speed715Prev.push_back(SoFar.second);716if (Prev.size() > 1 && SoFar.second == Prev[(Prev.size() - 1) / 2]) {717// Cycle detected718SoFar.second = nullptr;719break;720}721}722return SoFar;723}724725public:726ReferenceType(const Node *Pointee_, ReferenceKind RK_)727: Node(KReferenceType, Pointee_->getRHSComponentCache()),728Pointee(Pointee_), RK(RK_) {}729730template<typename Fn> void match(Fn F) const { F(Pointee, RK); }731732bool hasRHSComponentSlow(OutputBuffer &OB) const override {733return Pointee->hasRHSComponent(OB);734}735736void printLeft(OutputBuffer &OB) const override {737if (Printing)738return;739ScopedOverride<bool> SavePrinting(Printing, true);740std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);741if (!Collapsed.second)742return;743OB.printLeft(*Collapsed.second);744if (Collapsed.second->hasArray(OB))745OB += " ";746if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))747OB += "(";748749OB += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");750}751void printRight(OutputBuffer &OB) const override {752if (Printing)753return;754ScopedOverride<bool> SavePrinting(Printing, true);755std::pair<ReferenceKind, const Node *> Collapsed = collapse(OB);756if (!Collapsed.second)757return;758if (Collapsed.second->hasArray(OB) || Collapsed.second->hasFunction(OB))759OB += ")";760OB.printRight(*Collapsed.second);761}762};763764class PointerToMemberType final : public Node {765const Node *ClassType;766const Node *MemberType;767768public:769PointerToMemberType(const Node *ClassType_, const Node *MemberType_)770: Node(KPointerToMemberType, MemberType_->getRHSComponentCache()),771ClassType(ClassType_), MemberType(MemberType_) {}772773template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }774775bool hasRHSComponentSlow(OutputBuffer &OB) const override {776return MemberType->hasRHSComponent(OB);777}778779void printLeft(OutputBuffer &OB) const override {780OB.printLeft(*MemberType);781if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))782OB += "(";783else784OB += " ";785ClassType->print(OB);786OB += "::*";787}788789void printRight(OutputBuffer &OB) const override {790if (MemberType->hasArray(OB) || MemberType->hasFunction(OB))791OB += ")";792OB.printRight(*MemberType);793}794};795796class ArrayType final : public Node {797const Node *Base;798Node *Dimension;799800public:801ArrayType(const Node *Base_, Node *Dimension_)802: Node(KArrayType,803/*RHSComponentCache=*/Cache::Yes,804/*ArrayCache=*/Cache::Yes),805Base(Base_), Dimension(Dimension_) {}806807template<typename Fn> void match(Fn F) const { F(Base, Dimension); }808809bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }810bool hasArraySlow(OutputBuffer &) const override { return true; }811812void printLeft(OutputBuffer &OB) const override { OB.printLeft(*Base); }813814void printRight(OutputBuffer &OB) const override {815if (OB.back() != ']')816OB += " ";817OB += "[";818if (Dimension)819Dimension->print(OB);820OB += "]";821OB.printRight(*Base);822}823824bool printInitListAsType(OutputBuffer &OB,825const NodeArray &Elements) const override {826if (Base->getKind() == KNameType &&827static_cast<const NameType *>(Base)->getName() == "char") {828return Elements.printAsString(OB);829}830return false;831}832};833834class FunctionType final : public Node {835const Node *Ret;836NodeArray Params;837Qualifiers CVQuals;838FunctionRefQual RefQual;839const Node *ExceptionSpec;840841public:842FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,843FunctionRefQual RefQual_, const Node *ExceptionSpec_)844: Node(KFunctionType,845/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,846/*FunctionCache=*/Cache::Yes),847Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),848ExceptionSpec(ExceptionSpec_) {}849850template<typename Fn> void match(Fn F) const {851F(Ret, Params, CVQuals, RefQual, ExceptionSpec);852}853854bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }855bool hasFunctionSlow(OutputBuffer &) const override { return true; }856857// Handle C++'s ... quirky decl grammar by using the left & right858// distinction. Consider:859// int (*f(float))(char) {}860// f is a function that takes a float and returns a pointer to a function861// that takes a char and returns an int. If we're trying to print f, start862// by printing out the return types's left, then print our parameters, then863// finally print right of the return type.864void printLeft(OutputBuffer &OB) const override {865OB.printLeft(*Ret);866OB += " ";867}868869void printRight(OutputBuffer &OB) const override {870OB.printOpen();871Params.printWithComma(OB);872OB.printClose();873OB.printRight(*Ret);874875if (CVQuals & QualConst)876OB += " const";877if (CVQuals & QualVolatile)878OB += " volatile";879if (CVQuals & QualRestrict)880OB += " restrict";881882if (RefQual == FrefQualLValue)883OB += " &";884else if (RefQual == FrefQualRValue)885OB += " &&";886887if (ExceptionSpec != nullptr) {888OB += ' ';889ExceptionSpec->print(OB);890}891}892};893894class NoexceptSpec : public Node {895const Node *E;896public:897NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}898899template<typename Fn> void match(Fn F) const { F(E); }900901void printLeft(OutputBuffer &OB) const override {902OB += "noexcept";903OB.printOpen();904E->printAsOperand(OB);905OB.printClose();906}907};908909class DynamicExceptionSpec : public Node {910NodeArray Types;911public:912DynamicExceptionSpec(NodeArray Types_)913: Node(KDynamicExceptionSpec), Types(Types_) {}914915template<typename Fn> void match(Fn F) const { F(Types); }916917void printLeft(OutputBuffer &OB) const override {918OB += "throw";919OB.printOpen();920Types.printWithComma(OB);921OB.printClose();922}923};924925/// Represents the explicitly named object parameter.926/// E.g.,927/// \code{.cpp}928/// struct Foo {929/// void bar(this Foo && self);930/// };931/// \endcode932class ExplicitObjectParameter final : public Node {933Node *Base;934935public:936ExplicitObjectParameter(Node *Base_)937: Node(KExplicitObjectParameter), Base(Base_) {938DEMANGLE_ASSERT(939Base != nullptr,940"Creating an ExplicitObjectParameter without a valid Base Node.");941}942943template <typename Fn> void match(Fn F) const { F(Base); }944945void printLeft(OutputBuffer &OB) const override {946OB += "this ";947Base->print(OB);948}949};950951class FunctionEncoding final : public Node {952const Node *Ret;953const Node *Name;954NodeArray Params;955const Node *Attrs;956const Node *Requires;957Qualifiers CVQuals;958FunctionRefQual RefQual;959960public:961FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,962const Node *Attrs_, const Node *Requires_,963Qualifiers CVQuals_, FunctionRefQual RefQual_)964: Node(KFunctionEncoding,965/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,966/*FunctionCache=*/Cache::Yes),967Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),968Requires(Requires_), CVQuals(CVQuals_), RefQual(RefQual_) {}969970template<typename Fn> void match(Fn F) const {971F(Ret, Name, Params, Attrs, Requires, CVQuals, RefQual);972}973974Qualifiers getCVQuals() const { return CVQuals; }975FunctionRefQual getRefQual() const { return RefQual; }976NodeArray getParams() const { return Params; }977const Node *getReturnType() const { return Ret; }978const Node *getAttrs() const { return Attrs; }979const Node *getRequires() const { return Requires; }980981bool hasRHSComponentSlow(OutputBuffer &) const override { return true; }982bool hasFunctionSlow(OutputBuffer &) const override { return true; }983984const Node *getName() const { return Name; }985986void printLeft(OutputBuffer &OB) const override {987if (Ret) {988OB.printLeft(*Ret);989if (!Ret->hasRHSComponent(OB))990OB += " ";991}992993Name->print(OB);994}995996void printRight(OutputBuffer &OB) const override {997OB.printOpen();998Params.printWithComma(OB);999OB.printClose();10001001if (Ret)1002OB.printRight(*Ret);10031004if (CVQuals & QualConst)1005OB += " const";1006if (CVQuals & QualVolatile)1007OB += " volatile";1008if (CVQuals & QualRestrict)1009OB += " restrict";10101011if (RefQual == FrefQualLValue)1012OB += " &";1013else if (RefQual == FrefQualRValue)1014OB += " &&";10151016if (Attrs != nullptr)1017Attrs->print(OB);10181019if (Requires != nullptr) {1020OB += " requires ";1021Requires->print(OB);1022}1023}1024};10251026class LiteralOperator : public Node {1027const Node *OpName;10281029public:1030LiteralOperator(const Node *OpName_)1031: Node(KLiteralOperator), OpName(OpName_) {}10321033template<typename Fn> void match(Fn F) const { F(OpName); }10341035void printLeft(OutputBuffer &OB) const override {1036OB += "operator\"\" ";1037OpName->print(OB);1038}1039};10401041class SpecialName final : public Node {1042const std::string_view Special;1043const Node *Child;10441045public:1046SpecialName(std::string_view Special_, const Node *Child_)1047: Node(KSpecialName), Special(Special_), Child(Child_) {}10481049template<typename Fn> void match(Fn F) const { F(Special, Child); }10501051void printLeft(OutputBuffer &OB) const override {1052OB += Special;1053Child->print(OB);1054}1055};10561057class CtorVtableSpecialName final : public Node {1058const Node *FirstType;1059const Node *SecondType;10601061public:1062CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)1063: Node(KCtorVtableSpecialName),1064FirstType(FirstType_), SecondType(SecondType_) {}10651066template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }10671068void printLeft(OutputBuffer &OB) const override {1069OB += "construction vtable for ";1070FirstType->print(OB);1071OB += "-in-";1072SecondType->print(OB);1073}1074};10751076struct NestedName : Node {1077Node *Qual;1078Node *Name;10791080NestedName(Node *Qual_, Node *Name_)1081: Node(KNestedName), Qual(Qual_), Name(Name_) {}10821083template<typename Fn> void match(Fn F) const { F(Qual, Name); }10841085std::string_view getBaseName() const override { return Name->getBaseName(); }10861087void printLeft(OutputBuffer &OB) const override {1088Qual->print(OB);1089OB += "::";1090Name->print(OB);1091}1092};10931094struct MemberLikeFriendName : Node {1095Node *Qual;1096Node *Name;10971098MemberLikeFriendName(Node *Qual_, Node *Name_)1099: Node(KMemberLikeFriendName), Qual(Qual_), Name(Name_) {}11001101template<typename Fn> void match(Fn F) const { F(Qual, Name); }11021103std::string_view getBaseName() const override { return Name->getBaseName(); }11041105void printLeft(OutputBuffer &OB) const override {1106Qual->print(OB);1107OB += "::friend ";1108Name->print(OB);1109}1110};11111112struct ModuleName : Node {1113ModuleName *Parent;1114Node *Name;1115bool IsPartition;11161117ModuleName(ModuleName *Parent_, Node *Name_, bool IsPartition_ = false)1118: Node(KModuleName), Parent(Parent_), Name(Name_),1119IsPartition(IsPartition_) {}11201121template <typename Fn> void match(Fn F) const {1122F(Parent, Name, IsPartition);1123}11241125void printLeft(OutputBuffer &OB) const override {1126if (Parent)1127Parent->print(OB);1128if (Parent || IsPartition)1129OB += IsPartition ? ':' : '.';1130Name->print(OB);1131}1132};11331134struct ModuleEntity : Node {1135ModuleName *Module;1136Node *Name;11371138ModuleEntity(ModuleName *Module_, Node *Name_)1139: Node(KModuleEntity), Module(Module_), Name(Name_) {}11401141template <typename Fn> void match(Fn F) const { F(Module, Name); }11421143std::string_view getBaseName() const override { return Name->getBaseName(); }11441145void printLeft(OutputBuffer &OB) const override {1146Name->print(OB);1147OB += '@';1148Module->print(OB);1149}1150};11511152struct LocalName : Node {1153Node *Encoding;1154Node *Entity;11551156LocalName(Node *Encoding_, Node *Entity_)1157: Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}11581159template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }11601161void printLeft(OutputBuffer &OB) const override {1162Encoding->print(OB);1163OB += "::";1164Entity->print(OB);1165}1166};11671168class QualifiedName final : public Node {1169// qualifier::name1170const Node *Qualifier;1171const Node *Name;11721173public:1174QualifiedName(const Node *Qualifier_, const Node *Name_)1175: Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}11761177template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }11781179std::string_view getBaseName() const override { return Name->getBaseName(); }11801181void printLeft(OutputBuffer &OB) const override {1182Qualifier->print(OB);1183OB += "::";1184Name->print(OB);1185}1186};11871188class VectorType final : public Node {1189const Node *BaseType;1190const Node *Dimension;11911192public:1193VectorType(const Node *BaseType_, const Node *Dimension_)1194: Node(KVectorType), BaseType(BaseType_), Dimension(Dimension_) {}11951196const Node *getBaseType() const { return BaseType; }1197const Node *getDimension() const { return Dimension; }11981199template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }12001201void printLeft(OutputBuffer &OB) const override {1202BaseType->print(OB);1203OB += " vector[";1204if (Dimension)1205Dimension->print(OB);1206OB += "]";1207}1208};12091210class PixelVectorType final : public Node {1211const Node *Dimension;12121213public:1214PixelVectorType(const Node *Dimension_)1215: Node(KPixelVectorType), Dimension(Dimension_) {}12161217template<typename Fn> void match(Fn F) const { F(Dimension); }12181219void printLeft(OutputBuffer &OB) const override {1220// FIXME: This should demangle as "vector pixel".1221OB += "pixel vector[";1222Dimension->print(OB);1223OB += "]";1224}1225};12261227class BinaryFPType final : public Node {1228const Node *Dimension;12291230public:1231BinaryFPType(const Node *Dimension_)1232: Node(KBinaryFPType), Dimension(Dimension_) {}12331234template<typename Fn> void match(Fn F) const { F(Dimension); }12351236void printLeft(OutputBuffer &OB) const override {1237OB += "_Float";1238Dimension->print(OB);1239}1240};12411242enum class TemplateParamKind { Type, NonType, Template };12431244/// An invented name for a template parameter for which we don't have a1245/// corresponding template argument.1246///1247/// This node is created when parsing the <lambda-sig> for a lambda with1248/// explicit template arguments, which might be referenced in the parameter1249/// types appearing later in the <lambda-sig>.1250class SyntheticTemplateParamName final : public Node {1251TemplateParamKind Kind;1252unsigned Index;12531254public:1255SyntheticTemplateParamName(TemplateParamKind Kind_, unsigned Index_)1256: Node(KSyntheticTemplateParamName), Kind(Kind_), Index(Index_) {}12571258template<typename Fn> void match(Fn F) const { F(Kind, Index); }12591260void printLeft(OutputBuffer &OB) const override {1261switch (Kind) {1262case TemplateParamKind::Type:1263OB += "$T";1264break;1265case TemplateParamKind::NonType:1266OB += "$N";1267break;1268case TemplateParamKind::Template:1269OB += "$TT";1270break;1271}1272if (Index > 0)1273OB << Index - 1;1274}1275};12761277class TemplateParamQualifiedArg final : public Node {1278Node *Param;1279Node *Arg;12801281public:1282TemplateParamQualifiedArg(Node *Param_, Node *Arg_)1283: Node(KTemplateParamQualifiedArg), Param(Param_), Arg(Arg_) {}12841285template <typename Fn> void match(Fn F) const { F(Param, Arg); }12861287Node *getArg() { return Arg; }12881289void printLeft(OutputBuffer &OB) const override {1290// Don't print Param to keep the output consistent.1291Arg->print(OB);1292}1293};12941295/// A template type parameter declaration, 'typename T'.1296class TypeTemplateParamDecl final : public Node {1297Node *Name;12981299public:1300TypeTemplateParamDecl(Node *Name_)1301: Node(KTypeTemplateParamDecl, Cache::Yes), Name(Name_) {}13021303template<typename Fn> void match(Fn F) const { F(Name); }13041305void printLeft(OutputBuffer &OB) const override { OB += "typename "; }13061307void printRight(OutputBuffer &OB) const override { Name->print(OB); }1308};13091310/// A constrained template type parameter declaration, 'C<U> T'.1311class ConstrainedTypeTemplateParamDecl final : public Node {1312Node *Constraint;1313Node *Name;13141315public:1316ConstrainedTypeTemplateParamDecl(Node *Constraint_, Node *Name_)1317: Node(KConstrainedTypeTemplateParamDecl, Cache::Yes),1318Constraint(Constraint_), Name(Name_) {}13191320template<typename Fn> void match(Fn F) const { F(Constraint, Name); }13211322void printLeft(OutputBuffer &OB) const override {1323Constraint->print(OB);1324OB += " ";1325}13261327void printRight(OutputBuffer &OB) const override { Name->print(OB); }1328};13291330/// A non-type template parameter declaration, 'int N'.1331class NonTypeTemplateParamDecl final : public Node {1332Node *Name;1333Node *Type;13341335public:1336NonTypeTemplateParamDecl(Node *Name_, Node *Type_)1337: Node(KNonTypeTemplateParamDecl, Cache::Yes), Name(Name_), Type(Type_) {}13381339template<typename Fn> void match(Fn F) const { F(Name, Type); }13401341void printLeft(OutputBuffer &OB) const override {1342OB.printLeft(*Type);1343if (!Type->hasRHSComponent(OB))1344OB += " ";1345}13461347void printRight(OutputBuffer &OB) const override {1348Name->print(OB);1349OB.printRight(*Type);1350}1351};13521353/// A template template parameter declaration,1354/// 'template<typename T> typename N'.1355class TemplateTemplateParamDecl final : public Node {1356Node *Name;1357NodeArray Params;1358Node *Requires;13591360public:1361TemplateTemplateParamDecl(Node *Name_, NodeArray Params_, Node *Requires_)1362: Node(KTemplateTemplateParamDecl, Cache::Yes), Name(Name_),1363Params(Params_), Requires(Requires_) {}13641365template <typename Fn> void match(Fn F) const { F(Name, Params, Requires); }13661367void printLeft(OutputBuffer &OB) const override {1368ScopedOverride<unsigned> LT(OB.GtIsGt, 0);1369OB += "template<";1370Params.printWithComma(OB);1371OB += "> typename ";1372}13731374void printRight(OutputBuffer &OB) const override {1375Name->print(OB);1376if (Requires != nullptr) {1377OB += " requires ";1378Requires->print(OB);1379}1380}1381};13821383/// A template parameter pack declaration, 'typename ...T'.1384class TemplateParamPackDecl final : public Node {1385Node *Param;13861387public:1388TemplateParamPackDecl(Node *Param_)1389: Node(KTemplateParamPackDecl, Cache::Yes), Param(Param_) {}13901391template<typename Fn> void match(Fn F) const { F(Param); }13921393void printLeft(OutputBuffer &OB) const override {1394OB.printLeft(*Param);1395OB += "...";1396}13971398void printRight(OutputBuffer &OB) const override { OB.printRight(*Param); }1399};14001401/// An unexpanded parameter pack (either in the expression or type context). If1402/// this AST is correct, this node will have a ParameterPackExpansion node above1403/// it.1404///1405/// This node is created when some <template-args> are found that apply to an1406/// <encoding>, and is stored in the TemplateParams table. In order for this to1407/// appear in the final AST, it has to referenced via a <template-param> (ie,1408/// T_).1409class ParameterPack final : public Node {1410NodeArray Data;14111412// Setup OutputBuffer for a pack expansion, unless we're already expanding1413// one.1414void initializePackExpansion(OutputBuffer &OB) const {1415if (OB.CurrentPackMax == std::numeric_limits<unsigned>::max()) {1416OB.CurrentPackMax = static_cast<unsigned>(Data.size());1417OB.CurrentPackIndex = 0;1418}1419}14201421public:1422ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {1423ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;1424if (std::all_of(Data.begin(), Data.end(),1425[](Node *P) { return P->getArrayCache() == Cache::No; }))1426ArrayCache = Cache::No;1427if (std::all_of(Data.begin(), Data.end(),1428[](Node *P) { return P->getFunctionCache() == Cache::No; }))1429FunctionCache = Cache::No;1430if (std::all_of(Data.begin(), Data.end(), [](Node *P) {1431return P->getRHSComponentCache() == Cache::No;1432}))1433RHSComponentCache = Cache::No;1434}14351436template<typename Fn> void match(Fn F) const { F(Data); }14371438bool hasRHSComponentSlow(OutputBuffer &OB) const override {1439initializePackExpansion(OB);1440size_t Idx = OB.CurrentPackIndex;1441return Idx < Data.size() && Data[Idx]->hasRHSComponent(OB);1442}1443bool hasArraySlow(OutputBuffer &OB) const override {1444initializePackExpansion(OB);1445size_t Idx = OB.CurrentPackIndex;1446return Idx < Data.size() && Data[Idx]->hasArray(OB);1447}1448bool hasFunctionSlow(OutputBuffer &OB) const override {1449initializePackExpansion(OB);1450size_t Idx = OB.CurrentPackIndex;1451return Idx < Data.size() && Data[Idx]->hasFunction(OB);1452}1453const Node *getSyntaxNode(OutputBuffer &OB) const override {1454initializePackExpansion(OB);1455size_t Idx = OB.CurrentPackIndex;1456return Idx < Data.size() ? Data[Idx]->getSyntaxNode(OB) : this;1457}14581459void printLeft(OutputBuffer &OB) const override {1460initializePackExpansion(OB);1461size_t Idx = OB.CurrentPackIndex;1462if (Idx < Data.size())1463OB.printLeft(*Data[Idx]);1464}1465void printRight(OutputBuffer &OB) const override {1466initializePackExpansion(OB);1467size_t Idx = OB.CurrentPackIndex;1468if (Idx < Data.size())1469OB.printRight(*Data[Idx]);1470}1471};14721473/// A variadic template argument. This node represents an occurrence of1474/// J<something>E in some <template-args>. It isn't itself unexpanded, unless1475/// one of its Elements is. The parser inserts a ParameterPack into the1476/// TemplateParams table if the <template-args> this pack belongs to apply to an1477/// <encoding>.1478class TemplateArgumentPack final : public Node {1479NodeArray Elements;1480public:1481TemplateArgumentPack(NodeArray Elements_)1482: Node(KTemplateArgumentPack), Elements(Elements_) {}14831484template<typename Fn> void match(Fn F) const { F(Elements); }14851486NodeArray getElements() const { return Elements; }14871488void printLeft(OutputBuffer &OB) const override {1489Elements.printWithComma(OB);1490}1491};14921493/// A pack expansion. Below this node, there are some unexpanded ParameterPacks1494/// which each have Child->ParameterPackSize elements.1495class ParameterPackExpansion final : public Node {1496const Node *Child;14971498public:1499ParameterPackExpansion(const Node *Child_)1500: Node(KParameterPackExpansion), Child(Child_) {}15011502template<typename Fn> void match(Fn F) const { F(Child); }15031504const Node *getChild() const { return Child; }15051506void printLeft(OutputBuffer &OB) const override {1507constexpr unsigned Max = std::numeric_limits<unsigned>::max();1508ScopedOverride<unsigned> SavePackIdx(OB.CurrentPackIndex, Max);1509ScopedOverride<unsigned> SavePackMax(OB.CurrentPackMax, Max);1510size_t StreamPos = OB.getCurrentPosition();15111512// Print the first element in the pack. If Child contains a ParameterPack,1513// it will set up S.CurrentPackMax and print the first element.1514Child->print(OB);15151516// No ParameterPack was found in Child. This can occur if we've found a pack1517// expansion on a <function-param>.1518if (OB.CurrentPackMax == Max) {1519OB += "...";1520return;1521}15221523// We found a ParameterPack, but it has no elements. Erase whatever we may1524// of printed.1525if (OB.CurrentPackMax == 0) {1526OB.setCurrentPosition(StreamPos);1527return;1528}15291530// Else, iterate through the rest of the elements in the pack.1531for (unsigned I = 1, E = OB.CurrentPackMax; I < E; ++I) {1532OB += ", ";1533OB.CurrentPackIndex = I;1534Child->print(OB);1535}1536}1537};15381539class TemplateArgs final : public Node {1540NodeArray Params;1541Node *Requires;15421543public:1544TemplateArgs(NodeArray Params_, Node *Requires_)1545: Node(KTemplateArgs), Params(Params_), Requires(Requires_) {}15461547template<typename Fn> void match(Fn F) const { F(Params, Requires); }15481549NodeArray getParams() { return Params; }15501551void printLeft(OutputBuffer &OB) const override {1552ScopedOverride<unsigned> LT(OB.GtIsGt, 0);1553OB += "<";1554Params.printWithComma(OB);1555OB += ">";1556// Don't print the requires clause to keep the output simple.1557}1558};15591560/// A forward-reference to a template argument that was not known at the point1561/// where the template parameter name was parsed in a mangling.1562///1563/// This is created when demangling the name of a specialization of a1564/// conversion function template:1565///1566/// \code1567/// struct A {1568/// template<typename T> operator T*();1569/// };1570/// \endcode1571///1572/// When demangling a specialization of the conversion function template, we1573/// encounter the name of the template (including the \c T) before we reach1574/// the template argument list, so we cannot substitute the parameter name1575/// for the corresponding argument while parsing. Instead, we create a1576/// \c ForwardTemplateReference node that is resolved after we parse the1577/// template arguments.1578struct ForwardTemplateReference : Node {1579size_t Index;1580Node *Ref = nullptr;15811582// If we're currently printing this node. It is possible (though invalid) for1583// a forward template reference to refer to itself via a substitution. This1584// creates a cyclic AST, which will stack overflow printing. To fix this, bail1585// out if more than one print* function is active.1586mutable bool Printing = false;15871588ForwardTemplateReference(size_t Index_)1589: Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,1590Cache::Unknown),1591Index(Index_) {}15921593// We don't provide a matcher for these, because the value of the node is1594// not determined by its construction parameters, and it generally needs1595// special handling.1596template<typename Fn> void match(Fn F) const = delete;15971598bool hasRHSComponentSlow(OutputBuffer &OB) const override {1599if (Printing)1600return false;1601ScopedOverride<bool> SavePrinting(Printing, true);1602return Ref->hasRHSComponent(OB);1603}1604bool hasArraySlow(OutputBuffer &OB) const override {1605if (Printing)1606return false;1607ScopedOverride<bool> SavePrinting(Printing, true);1608return Ref->hasArray(OB);1609}1610bool hasFunctionSlow(OutputBuffer &OB) const override {1611if (Printing)1612return false;1613ScopedOverride<bool> SavePrinting(Printing, true);1614return Ref->hasFunction(OB);1615}1616const Node *getSyntaxNode(OutputBuffer &OB) const override {1617if (Printing)1618return this;1619ScopedOverride<bool> SavePrinting(Printing, true);1620return Ref->getSyntaxNode(OB);1621}16221623void printLeft(OutputBuffer &OB) const override {1624if (Printing)1625return;1626ScopedOverride<bool> SavePrinting(Printing, true);1627OB.printLeft(*Ref);1628}1629void printRight(OutputBuffer &OB) const override {1630if (Printing)1631return;1632ScopedOverride<bool> SavePrinting(Printing, true);1633OB.printRight(*Ref);1634}1635};16361637struct NameWithTemplateArgs : Node {1638// name<template_args>1639Node *Name;1640Node *TemplateArgs;16411642NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)1643: Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}16441645template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }16461647std::string_view getBaseName() const override { return Name->getBaseName(); }16481649void printLeft(OutputBuffer &OB) const override {1650Name->print(OB);1651TemplateArgs->print(OB);1652}1653};16541655class GlobalQualifiedName final : public Node {1656Node *Child;16571658public:1659GlobalQualifiedName(Node* Child_)1660: Node(KGlobalQualifiedName), Child(Child_) {}16611662template<typename Fn> void match(Fn F) const { F(Child); }16631664std::string_view getBaseName() const override { return Child->getBaseName(); }16651666void printLeft(OutputBuffer &OB) const override {1667OB += "::";1668Child->print(OB);1669}1670};16711672enum class SpecialSubKind {1673allocator,1674basic_string,1675string,1676istream,1677ostream,1678iostream,1679};16801681class SpecialSubstitution;1682class ExpandedSpecialSubstitution : public Node {1683protected:1684SpecialSubKind SSK;16851686ExpandedSpecialSubstitution(SpecialSubKind SSK_, Kind K_)1687: Node(K_), SSK(SSK_) {}1688public:1689ExpandedSpecialSubstitution(SpecialSubKind SSK_)1690: ExpandedSpecialSubstitution(SSK_, KExpandedSpecialSubstitution) {}1691inline ExpandedSpecialSubstitution(SpecialSubstitution const *);16921693template<typename Fn> void match(Fn F) const { F(SSK); }16941695protected:1696bool isInstantiation() const {1697return unsigned(SSK) >= unsigned(SpecialSubKind::string);1698}16991700std::string_view getBaseName() const override {1701switch (SSK) {1702case SpecialSubKind::allocator:1703return {"allocator"};1704case SpecialSubKind::basic_string:1705return {"basic_string"};1706case SpecialSubKind::string:1707return {"basic_string"};1708case SpecialSubKind::istream:1709return {"basic_istream"};1710case SpecialSubKind::ostream:1711return {"basic_ostream"};1712case SpecialSubKind::iostream:1713return {"basic_iostream"};1714}1715DEMANGLE_UNREACHABLE;1716}17171718private:1719void printLeft(OutputBuffer &OB) const override {1720OB << "std::" << getBaseName();1721if (isInstantiation()) {1722OB << "<char, std::char_traits<char>";1723if (SSK == SpecialSubKind::string)1724OB << ", std::allocator<char>";1725OB << ">";1726}1727}1728};17291730class SpecialSubstitution final : public ExpandedSpecialSubstitution {1731public:1732SpecialSubstitution(SpecialSubKind SSK_)1733: ExpandedSpecialSubstitution(SSK_, KSpecialSubstitution) {}17341735template<typename Fn> void match(Fn F) const { F(SSK); }17361737std::string_view getBaseName() const override {1738std::string_view SV = ExpandedSpecialSubstitution::getBaseName();1739if (isInstantiation()) {1740// The instantiations are typedefs that drop the "basic_" prefix.1741DEMANGLE_ASSERT(starts_with(SV, "basic_"), "");1742SV.remove_prefix(sizeof("basic_") - 1);1743}1744return SV;1745}17461747void printLeft(OutputBuffer &OB) const override {1748OB << "std::" << getBaseName();1749}1750};17511752inline ExpandedSpecialSubstitution::ExpandedSpecialSubstitution(1753SpecialSubstitution const *SS)1754: ExpandedSpecialSubstitution(SS->SSK) {}17551756class CtorDtorName final : public Node {1757const Node *Basename;1758const bool IsDtor;1759const int Variant;17601761public:1762CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)1763: Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),1764Variant(Variant_) {}17651766template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }17671768void printLeft(OutputBuffer &OB) const override {1769if (IsDtor)1770OB += "~";1771OB += Basename->getBaseName();1772}1773};17741775class DtorName : public Node {1776const Node *Base;17771778public:1779DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}17801781template<typename Fn> void match(Fn F) const { F(Base); }17821783void printLeft(OutputBuffer &OB) const override {1784OB += "~";1785OB.printLeft(*Base);1786}1787};17881789class UnnamedTypeName : public Node {1790const std::string_view Count;17911792public:1793UnnamedTypeName(std::string_view Count_)1794: Node(KUnnamedTypeName), Count(Count_) {}17951796template<typename Fn> void match(Fn F) const { F(Count); }17971798void printLeft(OutputBuffer &OB) const override {1799OB += "'unnamed";1800OB += Count;1801OB += "\'";1802}1803};18041805class ClosureTypeName : public Node {1806NodeArray TemplateParams;1807const Node *Requires1;1808NodeArray Params;1809const Node *Requires2;1810std::string_view Count;18111812public:1813ClosureTypeName(NodeArray TemplateParams_, const Node *Requires1_,1814NodeArray Params_, const Node *Requires2_,1815std::string_view Count_)1816: Node(KClosureTypeName), TemplateParams(TemplateParams_),1817Requires1(Requires1_), Params(Params_), Requires2(Requires2_),1818Count(Count_) {}18191820template<typename Fn> void match(Fn F) const {1821F(TemplateParams, Requires1, Params, Requires2, Count);1822}18231824void printDeclarator(OutputBuffer &OB) const {1825if (!TemplateParams.empty()) {1826ScopedOverride<unsigned> LT(OB.GtIsGt, 0);1827OB += "<";1828TemplateParams.printWithComma(OB);1829OB += ">";1830}1831if (Requires1 != nullptr) {1832OB += " requires ";1833Requires1->print(OB);1834OB += " ";1835}1836OB.printOpen();1837Params.printWithComma(OB);1838OB.printClose();1839if (Requires2 != nullptr) {1840OB += " requires ";1841Requires2->print(OB);1842}1843}18441845void printLeft(OutputBuffer &OB) const override {1846// FIXME: This demangling is not particularly readable.1847OB += "\'lambda";1848OB += Count;1849OB += "\'";1850printDeclarator(OB);1851}1852};18531854class StructuredBindingName : public Node {1855NodeArray Bindings;1856public:1857StructuredBindingName(NodeArray Bindings_)1858: Node(KStructuredBindingName), Bindings(Bindings_) {}18591860template<typename Fn> void match(Fn F) const { F(Bindings); }18611862void printLeft(OutputBuffer &OB) const override {1863OB.printOpen('[');1864Bindings.printWithComma(OB);1865OB.printClose(']');1866}1867};18681869// -- Expression Nodes --18701871class BinaryExpr : public Node {1872const Node *LHS;1873const std::string_view InfixOperator;1874const Node *RHS;18751876public:1877BinaryExpr(const Node *LHS_, std::string_view InfixOperator_,1878const Node *RHS_, Prec Prec_)1879: Node(KBinaryExpr, Prec_), LHS(LHS_), InfixOperator(InfixOperator_),1880RHS(RHS_) {}18811882template <typename Fn> void match(Fn F) const {1883F(LHS, InfixOperator, RHS, getPrecedence());1884}18851886void printLeft(OutputBuffer &OB) const override {1887bool ParenAll = OB.isGtInsideTemplateArgs() &&1888(InfixOperator == ">" || InfixOperator == ">>");1889if (ParenAll)1890OB.printOpen();1891// Assignment is right associative, with special LHS precedence.1892bool IsAssign = getPrecedence() == Prec::Assign;1893LHS->printAsOperand(OB, IsAssign ? Prec::OrIf : getPrecedence(), !IsAssign);1894// No space before comma operator1895if (!(InfixOperator == ","))1896OB += " ";1897OB += InfixOperator;1898OB += " ";1899RHS->printAsOperand(OB, getPrecedence(), IsAssign);1900if (ParenAll)1901OB.printClose();1902}1903};19041905class ArraySubscriptExpr : public Node {1906const Node *Op1;1907const Node *Op2;19081909public:1910ArraySubscriptExpr(const Node *Op1_, const Node *Op2_, Prec Prec_)1911: Node(KArraySubscriptExpr, Prec_), Op1(Op1_), Op2(Op2_) {}19121913template <typename Fn> void match(Fn F) const {1914F(Op1, Op2, getPrecedence());1915}19161917void printLeft(OutputBuffer &OB) const override {1918Op1->printAsOperand(OB, getPrecedence());1919OB.printOpen('[');1920Op2->printAsOperand(OB);1921OB.printClose(']');1922}1923};19241925class PostfixExpr : public Node {1926const Node *Child;1927const std::string_view Operator;19281929public:1930PostfixExpr(const Node *Child_, std::string_view Operator_, Prec Prec_)1931: Node(KPostfixExpr, Prec_), Child(Child_), Operator(Operator_) {}19321933template <typename Fn> void match(Fn F) const {1934F(Child, Operator, getPrecedence());1935}19361937void printLeft(OutputBuffer &OB) const override {1938Child->printAsOperand(OB, getPrecedence(), true);1939OB += Operator;1940}1941};19421943class ConditionalExpr : public Node {1944const Node *Cond;1945const Node *Then;1946const Node *Else;19471948public:1949ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_,1950Prec Prec_)1951: Node(KConditionalExpr, Prec_), Cond(Cond_), Then(Then_), Else(Else_) {}19521953template <typename Fn> void match(Fn F) const {1954F(Cond, Then, Else, getPrecedence());1955}19561957void printLeft(OutputBuffer &OB) const override {1958Cond->printAsOperand(OB, getPrecedence());1959OB += " ? ";1960Then->printAsOperand(OB);1961OB += " : ";1962Else->printAsOperand(OB, Prec::Assign, true);1963}1964};19651966class MemberExpr : public Node {1967const Node *LHS;1968const std::string_view Kind;1969const Node *RHS;19701971public:1972MemberExpr(const Node *LHS_, std::string_view Kind_, const Node *RHS_,1973Prec Prec_)1974: Node(KMemberExpr, Prec_), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}19751976template <typename Fn> void match(Fn F) const {1977F(LHS, Kind, RHS, getPrecedence());1978}19791980void printLeft(OutputBuffer &OB) const override {1981LHS->printAsOperand(OB, getPrecedence(), true);1982OB += Kind;1983RHS->printAsOperand(OB, getPrecedence(), false);1984}1985};19861987class SubobjectExpr : public Node {1988const Node *Type;1989const Node *SubExpr;1990std::string_view Offset;1991NodeArray UnionSelectors;1992bool OnePastTheEnd;19931994public:1995SubobjectExpr(const Node *Type_, const Node *SubExpr_,1996std::string_view Offset_, NodeArray UnionSelectors_,1997bool OnePastTheEnd_)1998: Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_),1999UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {}20002001template<typename Fn> void match(Fn F) const {2002F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd);2003}20042005void printLeft(OutputBuffer &OB) const override {2006SubExpr->print(OB);2007OB += ".<";2008Type->print(OB);2009OB += " at offset ";2010if (Offset.empty()) {2011OB += "0";2012} else if (Offset[0] == 'n') {2013OB += "-";2014OB += std::string_view(Offset.data() + 1, Offset.size() - 1);2015} else {2016OB += Offset;2017}2018OB += ">";2019}2020};20212022class EnclosingExpr : public Node {2023const std::string_view Prefix;2024const Node *Infix;2025const std::string_view Postfix;20262027public:2028EnclosingExpr(std::string_view Prefix_, const Node *Infix_,2029Prec Prec_ = Prec::Primary)2030: Node(KEnclosingExpr, Prec_), Prefix(Prefix_), Infix(Infix_) {}20312032template <typename Fn> void match(Fn F) const {2033F(Prefix, Infix, getPrecedence());2034}20352036void printLeft(OutputBuffer &OB) const override {2037OB += Prefix;2038OB.printOpen();2039Infix->print(OB);2040OB.printClose();2041OB += Postfix;2042}2043};20442045class CastExpr : public Node {2046// cast_kind<to>(from)2047const std::string_view CastKind;2048const Node *To;2049const Node *From;20502051public:2052CastExpr(std::string_view CastKind_, const Node *To_, const Node *From_,2053Prec Prec_)2054: Node(KCastExpr, Prec_), CastKind(CastKind_), To(To_), From(From_) {}20552056template <typename Fn> void match(Fn F) const {2057F(CastKind, To, From, getPrecedence());2058}20592060void printLeft(OutputBuffer &OB) const override {2061OB += CastKind;2062{2063ScopedOverride<unsigned> LT(OB.GtIsGt, 0);2064OB += "<";2065OB.printLeft(*To);2066OB += ">";2067}2068OB.printOpen();2069From->printAsOperand(OB);2070OB.printClose();2071}2072};20732074class SizeofParamPackExpr : public Node {2075const Node *Pack;20762077public:2078SizeofParamPackExpr(const Node *Pack_)2079: Node(KSizeofParamPackExpr), Pack(Pack_) {}20802081template<typename Fn> void match(Fn F) const { F(Pack); }20822083void printLeft(OutputBuffer &OB) const override {2084OB += "sizeof...";2085OB.printOpen();2086ParameterPackExpansion PPE(Pack);2087PPE.printLeft(OB);2088OB.printClose();2089}2090};20912092class CallExpr : public Node {2093const Node *Callee;2094NodeArray Args;2095bool IsParen; // (func)(args ...) ?20962097public:2098CallExpr(const Node *Callee_, NodeArray Args_, bool IsParen_, Prec Prec_)2099: Node(KCallExpr, Prec_), Callee(Callee_), Args(Args_),2100IsParen(IsParen_) {}21012102template <typename Fn> void match(Fn F) const {2103F(Callee, Args, IsParen, getPrecedence());2104}21052106void printLeft(OutputBuffer &OB) const override {2107if (IsParen)2108OB.printOpen();2109Callee->print(OB);2110if (IsParen)2111OB.printClose();2112OB.printOpen();2113Args.printWithComma(OB);2114OB.printClose();2115}2116};21172118class NewExpr : public Node {2119// new (expr_list) type(init_list)2120NodeArray ExprList;2121Node *Type;2122NodeArray InitList;2123bool IsGlobal; // ::operator new ?2124bool IsArray; // new[] ?2125public:2126NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,2127bool IsArray_, Prec Prec_)2128: Node(KNewExpr, Prec_), ExprList(ExprList_), Type(Type_),2129InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}21302131template<typename Fn> void match(Fn F) const {2132F(ExprList, Type, InitList, IsGlobal, IsArray, getPrecedence());2133}21342135void printLeft(OutputBuffer &OB) const override {2136if (IsGlobal)2137OB += "::";2138OB += "new";2139if (IsArray)2140OB += "[]";2141if (!ExprList.empty()) {2142OB.printOpen();2143ExprList.printWithComma(OB);2144OB.printClose();2145}2146OB += " ";2147Type->print(OB);2148if (!InitList.empty()) {2149OB.printOpen();2150InitList.printWithComma(OB);2151OB.printClose();2152}2153}2154};21552156class DeleteExpr : public Node {2157Node *Op;2158bool IsGlobal;2159bool IsArray;21602161public:2162DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_, Prec Prec_)2163: Node(KDeleteExpr, Prec_), Op(Op_), IsGlobal(IsGlobal_),2164IsArray(IsArray_) {}21652166template <typename Fn> void match(Fn F) const {2167F(Op, IsGlobal, IsArray, getPrecedence());2168}21692170void printLeft(OutputBuffer &OB) const override {2171if (IsGlobal)2172OB += "::";2173OB += "delete";2174if (IsArray)2175OB += "[]";2176OB += ' ';2177Op->print(OB);2178}2179};21802181class PrefixExpr : public Node {2182std::string_view Prefix;2183Node *Child;21842185public:2186PrefixExpr(std::string_view Prefix_, Node *Child_, Prec Prec_)2187: Node(KPrefixExpr, Prec_), Prefix(Prefix_), Child(Child_) {}21882189template <typename Fn> void match(Fn F) const {2190F(Prefix, Child, getPrecedence());2191}21922193void printLeft(OutputBuffer &OB) const override {2194OB += Prefix;2195Child->printAsOperand(OB, getPrecedence());2196}2197};21982199class FunctionParam : public Node {2200std::string_view Number;22012202public:2203FunctionParam(std::string_view Number_)2204: Node(KFunctionParam), Number(Number_) {}22052206template<typename Fn> void match(Fn F) const { F(Number); }22072208void printLeft(OutputBuffer &OB) const override {2209OB += "fp";2210OB += Number;2211}2212};22132214class ConversionExpr : public Node {2215const Node *Type;2216NodeArray Expressions;22172218public:2219ConversionExpr(const Node *Type_, NodeArray Expressions_, Prec Prec_)2220: Node(KConversionExpr, Prec_), Type(Type_), Expressions(Expressions_) {}22212222template <typename Fn> void match(Fn F) const {2223F(Type, Expressions, getPrecedence());2224}22252226void printLeft(OutputBuffer &OB) const override {2227OB.printOpen();2228Type->print(OB);2229OB.printClose();2230OB.printOpen();2231Expressions.printWithComma(OB);2232OB.printClose();2233}2234};22352236class PointerToMemberConversionExpr : public Node {2237const Node *Type;2238const Node *SubExpr;2239std::string_view Offset;22402241public:2242PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_,2243std::string_view Offset_, Prec Prec_)2244: Node(KPointerToMemberConversionExpr, Prec_), Type(Type_),2245SubExpr(SubExpr_), Offset(Offset_) {}22462247template <typename Fn> void match(Fn F) const {2248F(Type, SubExpr, Offset, getPrecedence());2249}22502251void printLeft(OutputBuffer &OB) const override {2252OB.printOpen();2253Type->print(OB);2254OB.printClose();2255OB.printOpen();2256SubExpr->print(OB);2257OB.printClose();2258}2259};22602261class InitListExpr : public Node {2262const Node *Ty;2263NodeArray Inits;2264public:2265InitListExpr(const Node *Ty_, NodeArray Inits_)2266: Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}22672268template<typename Fn> void match(Fn F) const { F(Ty, Inits); }22692270void printLeft(OutputBuffer &OB) const override {2271if (Ty) {2272if (Ty->printInitListAsType(OB, Inits))2273return;2274Ty->print(OB);2275}2276OB += '{';2277Inits.printWithComma(OB);2278OB += '}';2279}2280};22812282class BracedExpr : public Node {2283const Node *Elem;2284const Node *Init;2285bool IsArray;2286public:2287BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)2288: Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}22892290template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }22912292void printLeft(OutputBuffer &OB) const override {2293if (IsArray) {2294OB += '[';2295Elem->print(OB);2296OB += ']';2297} else {2298OB += '.';2299Elem->print(OB);2300}2301if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2302OB += " = ";2303Init->print(OB);2304}2305};23062307class BracedRangeExpr : public Node {2308const Node *First;2309const Node *Last;2310const Node *Init;2311public:2312BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)2313: Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}23142315template<typename Fn> void match(Fn F) const { F(First, Last, Init); }23162317void printLeft(OutputBuffer &OB) const override {2318OB += '[';2319First->print(OB);2320OB += " ... ";2321Last->print(OB);2322OB += ']';2323if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)2324OB += " = ";2325Init->print(OB);2326}2327};23282329class FoldExpr : public Node {2330const Node *Pack, *Init;2331std::string_view OperatorName;2332bool IsLeftFold;23332334public:2335FoldExpr(bool IsLeftFold_, std::string_view OperatorName_, const Node *Pack_,2336const Node *Init_)2337: Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),2338IsLeftFold(IsLeftFold_) {}23392340template<typename Fn> void match(Fn F) const {2341F(IsLeftFold, OperatorName, Pack, Init);2342}23432344void printLeft(OutputBuffer &OB) const override {2345auto PrintPack = [&] {2346OB.printOpen();2347ParameterPackExpansion(Pack).print(OB);2348OB.printClose();2349};23502351OB.printOpen();2352// Either '[init op ]... op pack' or 'pack op ...[ op init]'2353// Refactored to '[(init|pack) op ]...[ op (pack|init)]'2354// Fold expr operands are cast-expressions2355if (!IsLeftFold || Init != nullptr) {2356// '(init|pack) op '2357if (IsLeftFold)2358Init->printAsOperand(OB, Prec::Cast, true);2359else2360PrintPack();2361OB << " " << OperatorName << " ";2362}2363OB << "...";2364if (IsLeftFold || Init != nullptr) {2365// ' op (init|pack)'2366OB << " " << OperatorName << " ";2367if (IsLeftFold)2368PrintPack();2369else2370Init->printAsOperand(OB, Prec::Cast, true);2371}2372OB.printClose();2373}2374};23752376class ThrowExpr : public Node {2377const Node *Op;23782379public:2380ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}23812382template<typename Fn> void match(Fn F) const { F(Op); }23832384void printLeft(OutputBuffer &OB) const override {2385OB += "throw ";2386Op->print(OB);2387}2388};23892390class BoolExpr : public Node {2391bool Value;23922393public:2394BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}23952396template<typename Fn> void match(Fn F) const { F(Value); }23972398void printLeft(OutputBuffer &OB) const override {2399OB += Value ? std::string_view("true") : std::string_view("false");2400}2401};24022403class StringLiteral : public Node {2404const Node *Type;24052406public:2407StringLiteral(const Node *Type_) : Node(KStringLiteral), Type(Type_) {}24082409template<typename Fn> void match(Fn F) const { F(Type); }24102411void printLeft(OutputBuffer &OB) const override {2412OB += "\"<";2413Type->print(OB);2414OB += ">\"";2415}2416};24172418class LambdaExpr : public Node {2419const Node *Type;24202421public:2422LambdaExpr(const Node *Type_) : Node(KLambdaExpr), Type(Type_) {}24232424template<typename Fn> void match(Fn F) const { F(Type); }24252426void printLeft(OutputBuffer &OB) const override {2427OB += "[]";2428if (Type->getKind() == KClosureTypeName)2429static_cast<const ClosureTypeName *>(Type)->printDeclarator(OB);2430OB += "{...}";2431}2432};24332434class EnumLiteral : public Node {2435// ty(integer)2436const Node *Ty;2437std::string_view Integer;24382439public:2440EnumLiteral(const Node *Ty_, std::string_view Integer_)2441: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}24422443template<typename Fn> void match(Fn F) const { F(Ty, Integer); }24442445void printLeft(OutputBuffer &OB) const override {2446OB.printOpen();2447Ty->print(OB);2448OB.printClose();24492450if (Integer[0] == 'n')2451OB << '-' << std::string_view(Integer.data() + 1, Integer.size() - 1);2452else2453OB << Integer;2454}2455};24562457class IntegerLiteral : public Node {2458std::string_view Type;2459std::string_view Value;24602461public:2462IntegerLiteral(std::string_view Type_, std::string_view Value_)2463: Node(KIntegerLiteral), Type(Type_), Value(Value_) {}24642465template<typename Fn> void match(Fn F) const { F(Type, Value); }24662467void printLeft(OutputBuffer &OB) const override {2468if (Type.size() > 3) {2469OB.printOpen();2470OB += Type;2471OB.printClose();2472}24732474if (Value[0] == 'n')2475OB << '-' << std::string_view(Value.data() + 1, Value.size() - 1);2476else2477OB += Value;24782479if (Type.size() <= 3)2480OB += Type;2481}24822483std::string_view value() const { return Value; }2484};24852486class RequiresExpr : public Node {2487NodeArray Parameters;2488NodeArray Requirements;2489public:2490RequiresExpr(NodeArray Parameters_, NodeArray Requirements_)2491: Node(KRequiresExpr), Parameters(Parameters_),2492Requirements(Requirements_) {}24932494template<typename Fn> void match(Fn F) const { F(Parameters, Requirements); }24952496void printLeft(OutputBuffer &OB) const override {2497OB += "requires";2498if (!Parameters.empty()) {2499OB += ' ';2500OB.printOpen();2501Parameters.printWithComma(OB);2502OB.printClose();2503}2504OB += ' ';2505OB.printOpen('{');2506for (const Node *Req : Requirements) {2507Req->print(OB);2508}2509OB += ' ';2510OB.printClose('}');2511}2512};25132514class ExprRequirement : public Node {2515const Node *Expr;2516bool IsNoexcept;2517const Node *TypeConstraint;2518public:2519ExprRequirement(const Node *Expr_, bool IsNoexcept_,2520const Node *TypeConstraint_)2521: Node(KExprRequirement), Expr(Expr_), IsNoexcept(IsNoexcept_),2522TypeConstraint(TypeConstraint_) {}25232524template <typename Fn> void match(Fn F) const {2525F(Expr, IsNoexcept, TypeConstraint);2526}25272528void printLeft(OutputBuffer &OB) const override {2529OB += " ";2530if (IsNoexcept || TypeConstraint)2531OB.printOpen('{');2532Expr->print(OB);2533if (IsNoexcept || TypeConstraint)2534OB.printClose('}');2535if (IsNoexcept)2536OB += " noexcept";2537if (TypeConstraint) {2538OB += " -> ";2539TypeConstraint->print(OB);2540}2541OB += ';';2542}2543};25442545class TypeRequirement : public Node {2546const Node *Type;2547public:2548TypeRequirement(const Node *Type_)2549: Node(KTypeRequirement), Type(Type_) {}25502551template <typename Fn> void match(Fn F) const { F(Type); }25522553void printLeft(OutputBuffer &OB) const override {2554OB += " typename ";2555Type->print(OB);2556OB += ';';2557}2558};25592560class NestedRequirement : public Node {2561const Node *Constraint;2562public:2563NestedRequirement(const Node *Constraint_)2564: Node(KNestedRequirement), Constraint(Constraint_) {}25652566template <typename Fn> void match(Fn F) const { F(Constraint); }25672568void printLeft(OutputBuffer &OB) const override {2569OB += " requires ";2570Constraint->print(OB);2571OB += ';';2572}2573};25742575template <class Float> struct FloatData;25762577namespace float_literal_impl {2578constexpr Node::Kind getFloatLiteralKind(float *) {2579return Node::KFloatLiteral;2580}2581constexpr Node::Kind getFloatLiteralKind(double *) {2582return Node::KDoubleLiteral;2583}2584constexpr Node::Kind getFloatLiteralKind(long double *) {2585return Node::KLongDoubleLiteral;2586}2587}25882589template <class Float> class FloatLiteralImpl : public Node {2590const std::string_view Contents;25912592static constexpr Kind KindForClass =2593float_literal_impl::getFloatLiteralKind((Float *)nullptr);25942595public:2596FloatLiteralImpl(std::string_view Contents_)2597: Node(KindForClass), Contents(Contents_) {}25982599template<typename Fn> void match(Fn F) const { F(Contents); }26002601void printLeft(OutputBuffer &OB) const override {2602const size_t N = FloatData<Float>::mangled_size;2603if (Contents.size() >= N) {2604union {2605Float value;2606char buf[sizeof(Float)];2607};2608const char *t = Contents.data();2609const char *last = t + N;2610char *e = buf;2611for (; t != last; ++t, ++e) {2612unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')2613: static_cast<unsigned>(*t - 'a' + 10);2614++t;2615unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')2616: static_cast<unsigned>(*t - 'a' + 10);2617*e = static_cast<char>((d1 << 4) + d0);2618}2619#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__2620std::reverse(buf, e);2621#endif2622char num[FloatData<Float>::max_demangled_size] = {0};2623int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);2624OB += std::string_view(num, n);2625}2626}2627};26282629using FloatLiteral = FloatLiteralImpl<float>;2630using DoubleLiteral = FloatLiteralImpl<double>;2631using LongDoubleLiteral = FloatLiteralImpl<long double>;26322633/// Visit the node. Calls \c F(P), where \c P is the node cast to the2634/// appropriate derived class.2635template<typename Fn>2636void Node::visit(Fn F) const {2637switch (K) {2638#define NODE(X) \2639case K##X: \2640return F(static_cast<const X *>(this));2641#include "ItaniumNodes.def"2642}2643DEMANGLE_ASSERT(0, "unknown mangling node kind");2644}26452646/// Determine the kind of a node from its type.2647template<typename NodeT> struct NodeKind;2648#define NODE(X) \2649template <> struct NodeKind<X> { \2650static constexpr Node::Kind Kind = Node::K##X; \2651static constexpr const char *name() { return #X; } \2652};2653#include "ItaniumNodes.def"26542655inline bool NodeArray::printAsString(OutputBuffer &OB) const {2656auto StartPos = OB.getCurrentPosition();2657auto Fail = [&OB, StartPos] {2658OB.setCurrentPosition(StartPos);2659return false;2660};26612662OB += '"';2663bool LastWasNumericEscape = false;2664for (const Node *Element : *this) {2665if (Element->getKind() != Node::KIntegerLiteral)2666return Fail();2667int integer_value = 0;2668for (char c : static_cast<const IntegerLiteral *>(Element)->value()) {2669if (c < '0' || c > '9' || integer_value > 25)2670return Fail();2671integer_value *= 10;2672integer_value += c - '0';2673}2674if (integer_value > 255)2675return Fail();26762677// Insert a `""` to avoid accidentally extending a numeric escape.2678if (LastWasNumericEscape) {2679if ((integer_value >= '0' && integer_value <= '9') ||2680(integer_value >= 'a' && integer_value <= 'f') ||2681(integer_value >= 'A' && integer_value <= 'F')) {2682OB += "\"\"";2683}2684}26852686LastWasNumericEscape = false;26872688// Determine how to print this character.2689switch (integer_value) {2690case '\a':2691OB += "\\a";2692break;2693case '\b':2694OB += "\\b";2695break;2696case '\f':2697OB += "\\f";2698break;2699case '\n':2700OB += "\\n";2701break;2702case '\r':2703OB += "\\r";2704break;2705case '\t':2706OB += "\\t";2707break;2708case '\v':2709OB += "\\v";2710break;27112712case '"':2713OB += "\\\"";2714break;2715case '\\':2716OB += "\\\\";2717break;27182719default:2720// We assume that the character is ASCII, and use a numeric escape for all2721// remaining non-printable ASCII characters.2722if (integer_value < 32 || integer_value == 127) {2723constexpr char Hex[] = "0123456789ABCDEF";2724OB += '\\';2725if (integer_value > 7)2726OB += 'x';2727if (integer_value >= 16)2728OB += Hex[integer_value >> 4];2729OB += Hex[integer_value & 0xF];2730LastWasNumericEscape = true;2731break;2732}27332734// Assume all remaining characters are directly printable.2735OB += (char)integer_value;2736break;2737}2738}2739OB += '"';2740return true;2741}27422743template <typename Derived, typename Alloc> struct AbstractManglingParser {2744const char *First;2745const char *Last;27462747// Name stack, this is used by the parser to hold temporary names that were2748// parsed. The parser collapses multiple names into new nodes to construct2749// the AST. Once the parser is finished, names.size() == 1.2750PODSmallVector<Node *, 32> Names;27512752// Substitution table. Itanium supports name substitutions as a means of2753// compression. The string "S42_" refers to the 44nd entry (base-36) in this2754// table.2755PODSmallVector<Node *, 32> Subs;27562757// A list of template argument values corresponding to a template parameter2758// list.2759using TemplateParamList = PODSmallVector<Node *, 8>;27602761class ScopedTemplateParamList {2762AbstractManglingParser *Parser;2763size_t OldNumTemplateParamLists;2764TemplateParamList Params;27652766public:2767ScopedTemplateParamList(AbstractManglingParser *TheParser)2768: Parser(TheParser),2769OldNumTemplateParamLists(TheParser->TemplateParams.size()) {2770Parser->TemplateParams.push_back(&Params);2771}2772~ScopedTemplateParamList() {2773DEMANGLE_ASSERT(Parser->TemplateParams.size() >= OldNumTemplateParamLists,2774"");2775Parser->TemplateParams.shrinkToSize(OldNumTemplateParamLists);2776}2777TemplateParamList *params() { return &Params; }2778};27792780// Template parameter table. Like the above, but referenced like "T42_".2781// This has a smaller size compared to Subs and Names because it can be2782// stored on the stack.2783TemplateParamList OuterTemplateParams;27842785// Lists of template parameters indexed by template parameter depth,2786// referenced like "TL2_4_". If nonempty, element 0 is always2787// OuterTemplateParams; inner elements are always template parameter lists of2788// lambda expressions. For a generic lambda with no explicit template2789// parameter list, the corresponding parameter list pointer will be null.2790PODSmallVector<TemplateParamList *, 4> TemplateParams;27912792class SaveTemplateParams {2793AbstractManglingParser *Parser;2794decltype(TemplateParams) OldParams;2795decltype(OuterTemplateParams) OldOuterParams;27962797public:2798SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) {2799OldParams = std::move(Parser->TemplateParams);2800OldOuterParams = std::move(Parser->OuterTemplateParams);2801Parser->TemplateParams.clear();2802Parser->OuterTemplateParams.clear();2803}2804~SaveTemplateParams() {2805Parser->TemplateParams = std::move(OldParams);2806Parser->OuterTemplateParams = std::move(OldOuterParams);2807}2808};28092810// Set of unresolved forward <template-param> references. These can occur in a2811// conversion operator's type, and are resolved in the enclosing <encoding>.2812PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;28132814bool TryToParseTemplateArgs = true;2815bool PermitForwardTemplateReferences = false;2816bool HasIncompleteTemplateParameterTracking = false;2817size_t ParsingLambdaParamsAtLevel = (size_t)-1;28182819unsigned NumSyntheticTemplateParameters[3] = {};28202821Alloc ASTAllocator;28222823AbstractManglingParser(const char *First_, const char *Last_)2824: First(First_), Last(Last_) {}28252826Derived &getDerived() { return static_cast<Derived &>(*this); }28272828void reset(const char *First_, const char *Last_) {2829First = First_;2830Last = Last_;2831Names.clear();2832Subs.clear();2833TemplateParams.clear();2834ParsingLambdaParamsAtLevel = (size_t)-1;2835TryToParseTemplateArgs = true;2836PermitForwardTemplateReferences = false;2837for (int I = 0; I != 3; ++I)2838NumSyntheticTemplateParameters[I] = 0;2839ASTAllocator.reset();2840}28412842template <class T, class... Args> Node *make(Args &&... args) {2843return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);2844}28452846template <class It> NodeArray makeNodeArray(It begin, It end) {2847size_t sz = static_cast<size_t>(end - begin);2848void *mem = ASTAllocator.allocateNodeArray(sz);2849Node **data = new (mem) Node *[sz];2850std::copy(begin, end, data);2851return NodeArray(data, sz);2852}28532854NodeArray popTrailingNodeArray(size_t FromPosition) {2855DEMANGLE_ASSERT(FromPosition <= Names.size(), "");2856NodeArray res =2857makeNodeArray(Names.begin() + (long)FromPosition, Names.end());2858Names.shrinkToSize(FromPosition);2859return res;2860}28612862bool consumeIf(std::string_view S) {2863if (starts_with(std::string_view(First, Last - First), S)) {2864First += S.size();2865return true;2866}2867return false;2868}28692870bool consumeIf(char C) {2871if (First != Last && *First == C) {2872++First;2873return true;2874}2875return false;2876}28772878char consume() { return First != Last ? *First++ : '\0'; }28792880char look(unsigned Lookahead = 0) const {2881if (static_cast<size_t>(Last - First) <= Lookahead)2882return '\0';2883return First[Lookahead];2884}28852886size_t numLeft() const { return static_cast<size_t>(Last - First); }28872888std::string_view parseNumber(bool AllowNegative = false);2889Qualifiers parseCVQualifiers();2890bool parsePositiveInteger(size_t *Out);2891std::string_view parseBareSourceName();28922893bool parseSeqId(size_t *Out);2894Node *parseSubstitution();2895Node *parseTemplateParam();2896Node *parseTemplateParamDecl(TemplateParamList *Params);2897Node *parseTemplateArgs(bool TagTemplates = false);2898Node *parseTemplateArg();28992900bool isTemplateParamDecl() {2901return look() == 'T' &&2902std::string_view("yptnk").find(look(1)) != std::string_view::npos;2903}29042905/// Parse the <expression> production.2906Node *parseExpr();2907Node *parsePrefixExpr(std::string_view Kind, Node::Prec Prec);2908Node *parseBinaryExpr(std::string_view Kind, Node::Prec Prec);2909Node *parseIntegerLiteral(std::string_view Lit);2910Node *parseExprPrimary();2911template <class Float> Node *parseFloatingLiteral();2912Node *parseFunctionParam();2913Node *parseConversionExpr();2914Node *parseBracedExpr();2915Node *parseFoldExpr();2916Node *parsePointerToMemberConversionExpr(Node::Prec Prec);2917Node *parseSubobjectExpr();2918Node *parseConstraintExpr();2919Node *parseRequiresExpr();29202921/// Parse the <type> production.2922Node *parseType();2923Node *parseFunctionType();2924Node *parseVectorType();2925Node *parseDecltype();2926Node *parseArrayType();2927Node *parsePointerToMemberType();2928Node *parseClassEnumType();2929Node *parseQualifiedType();29302931Node *parseEncoding(bool ParseParams = true);2932bool parseCallOffset();2933Node *parseSpecialName();29342935/// Holds some extra information about a <name> that is being parsed. This2936/// information is only pertinent if the <name> refers to an <encoding>.2937struct NameState {2938bool CtorDtorConversion = false;2939bool EndsWithTemplateArgs = false;2940Qualifiers CVQualifiers = QualNone;2941FunctionRefQual ReferenceQualifier = FrefQualNone;2942size_t ForwardTemplateRefsBegin;2943bool HasExplicitObjectParameter = false;29442945NameState(AbstractManglingParser *Enclosing)2946: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}2947};29482949bool resolveForwardTemplateRefs(NameState &State) {2950size_t I = State.ForwardTemplateRefsBegin;2951size_t E = ForwardTemplateRefs.size();2952for (; I < E; ++I) {2953size_t Idx = ForwardTemplateRefs[I]->Index;2954if (TemplateParams.empty() || !TemplateParams[0] ||2955Idx >= TemplateParams[0]->size())2956return true;2957ForwardTemplateRefs[I]->Ref = (*TemplateParams[0])[Idx];2958}2959ForwardTemplateRefs.shrinkToSize(State.ForwardTemplateRefsBegin);2960return false;2961}29622963/// Parse the <name> production>2964Node *parseName(NameState *State = nullptr);2965Node *parseLocalName(NameState *State);2966Node *parseOperatorName(NameState *State);2967bool parseModuleNameOpt(ModuleName *&Module);2968Node *parseUnqualifiedName(NameState *State, Node *Scope, ModuleName *Module);2969Node *parseUnnamedTypeName(NameState *State);2970Node *parseSourceName(NameState *State);2971Node *parseUnscopedName(NameState *State, bool *isSubstName);2972Node *parseNestedName(NameState *State);2973Node *parseCtorDtorName(Node *&SoFar, NameState *State);29742975Node *parseAbiTags(Node *N);29762977struct OperatorInfo {2978enum OIKind : unsigned char {2979Prefix, // Prefix unary: @ expr2980Postfix, // Postfix unary: expr @2981Binary, // Binary: lhs @ rhs2982Array, // Array index: lhs [ rhs ]2983Member, // Member access: lhs @ rhs2984New, // New2985Del, // Delete2986Call, // Function call: expr (expr*)2987CCast, // C cast: (type)expr2988Conditional, // Conditional: expr ? expr : expr2989NameOnly, // Overload only, not allowed in expression.2990// Below do not have operator names2991NamedCast, // Named cast, @<type>(expr)2992OfIdOp, // alignof, sizeof, typeid29932994Unnameable = NamedCast,2995};2996char Enc[2]; // Encoding2997OIKind Kind; // Kind of operator2998bool Flag : 1; // Entry-specific flag2999Node::Prec Prec : 7; // Precedence3000const char *Name; // Spelling30013002public:3003constexpr OperatorInfo(const char (&E)[3], OIKind K, bool F, Node::Prec P,3004const char *N)3005: Enc{E[0], E[1]}, Kind{K}, Flag{F}, Prec{P}, Name{N} {}30063007public:3008bool operator<(const OperatorInfo &Other) const {3009return *this < Other.Enc;3010}3011bool operator<(const char *Peek) const {3012return Enc[0] < Peek[0] || (Enc[0] == Peek[0] && Enc[1] < Peek[1]);3013}3014bool operator==(const char *Peek) const {3015return Enc[0] == Peek[0] && Enc[1] == Peek[1];3016}3017bool operator!=(const char *Peek) const { return !this->operator==(Peek); }30183019public:3020std::string_view getSymbol() const {3021std::string_view Res = Name;3022if (Kind < Unnameable) {3023DEMANGLE_ASSERT(starts_with(Res, "operator"),3024"operator name does not start with 'operator'");3025Res.remove_prefix(sizeof("operator") - 1);3026if (starts_with(Res, ' '))3027Res.remove_prefix(1);3028}3029return Res;3030}3031std::string_view getName() const { return Name; }3032OIKind getKind() const { return Kind; }3033bool getFlag() const { return Flag; }3034Node::Prec getPrecedence() const { return Prec; }3035};3036static const OperatorInfo Ops[];3037static const size_t NumOps;3038const OperatorInfo *parseOperatorEncoding();30393040/// Parse the <unresolved-name> production.3041Node *parseUnresolvedName(bool Global);3042Node *parseSimpleId();3043Node *parseBaseUnresolvedName();3044Node *parseUnresolvedType();3045Node *parseDestructorName();30463047/// Top-level entry point into the parser.3048Node *parse(bool ParseParams = true);3049};30503051const char* parse_discriminator(const char* first, const char* last);30523053// <name> ::= <nested-name> // N3054// ::= <local-name> # See Scope Encoding below // Z3055// ::= <unscoped-template-name> <template-args>3056// ::= <unscoped-name>3057//3058// <unscoped-template-name> ::= <unscoped-name>3059// ::= <substitution>3060template <typename Derived, typename Alloc>3061Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {3062if (look() == 'N')3063return getDerived().parseNestedName(State);3064if (look() == 'Z')3065return getDerived().parseLocalName(State);30663067Node *Result = nullptr;3068bool IsSubst = false;30693070Result = getDerived().parseUnscopedName(State, &IsSubst);3071if (!Result)3072return nullptr;30733074if (look() == 'I') {3075// ::= <unscoped-template-name> <template-args>3076if (!IsSubst)3077// An unscoped-template-name is substitutable.3078Subs.push_back(Result);3079Node *TA = getDerived().parseTemplateArgs(State != nullptr);3080if (TA == nullptr)3081return nullptr;3082if (State)3083State->EndsWithTemplateArgs = true;3084Result = make<NameWithTemplateArgs>(Result, TA);3085} else if (IsSubst) {3086// The substitution case must be followed by <template-args>.3087return nullptr;3088}30893090return Result;3091}30923093// <local-name> := Z <function encoding> E <entity name> [<discriminator>]3094// := Z <function encoding> E s [<discriminator>]3095// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>3096template <typename Derived, typename Alloc>3097Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {3098if (!consumeIf('Z'))3099return nullptr;3100Node *Encoding = getDerived().parseEncoding();3101if (Encoding == nullptr || !consumeIf('E'))3102return nullptr;31033104if (consumeIf('s')) {3105First = parse_discriminator(First, Last);3106auto *StringLitName = make<NameType>("string literal");3107if (!StringLitName)3108return nullptr;3109return make<LocalName>(Encoding, StringLitName);3110}31113112// The template parameters of the inner name are unrelated to those of the3113// enclosing context.3114SaveTemplateParams SaveTemplateParamsScope(this);31153116if (consumeIf('d')) {3117parseNumber(true);3118if (!consumeIf('_'))3119return nullptr;3120Node *N = getDerived().parseName(State);3121if (N == nullptr)3122return nullptr;3123return make<LocalName>(Encoding, N);3124}31253126Node *Entity = getDerived().parseName(State);3127if (Entity == nullptr)3128return nullptr;3129First = parse_discriminator(First, Last);3130return make<LocalName>(Encoding, Entity);3131}31323133// <unscoped-name> ::= <unqualified-name>3134// ::= St <unqualified-name> # ::std::3135// [*] extension3136template <typename Derived, typename Alloc>3137Node *3138AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State,3139bool *IsSubst) {31403141Node *Std = nullptr;3142if (consumeIf("St")) {3143Std = make<NameType>("std");3144if (Std == nullptr)3145return nullptr;3146}31473148Node *Res = nullptr;3149ModuleName *Module = nullptr;3150if (look() == 'S') {3151Node *S = getDerived().parseSubstitution();3152if (!S)3153return nullptr;3154if (S->getKind() == Node::KModuleName)3155Module = static_cast<ModuleName *>(S);3156else if (IsSubst && Std == nullptr) {3157Res = S;3158*IsSubst = true;3159} else {3160return nullptr;3161}3162}31633164if (Res == nullptr || Std != nullptr) {3165Res = getDerived().parseUnqualifiedName(State, Std, Module);3166}31673168return Res;3169}31703171// <unqualified-name> ::= [<module-name>] F? L? <operator-name> [<abi-tags>]3172// ::= [<module-name>] <ctor-dtor-name> [<abi-tags>]3173// ::= [<module-name>] F? L? <source-name> [<abi-tags>]3174// ::= [<module-name>] L? <unnamed-type-name> [<abi-tags>]3175// # structured binding declaration3176// ::= [<module-name>] L? DC <source-name>+ E3177template <typename Derived, typename Alloc>3178Node *AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(3179NameState *State, Node *Scope, ModuleName *Module) {3180if (getDerived().parseModuleNameOpt(Module))3181return nullptr;31823183bool IsMemberLikeFriend = Scope && consumeIf('F');31843185consumeIf('L');31863187Node *Result;3188if (look() >= '1' && look() <= '9') {3189Result = getDerived().parseSourceName(State);3190} else if (look() == 'U') {3191Result = getDerived().parseUnnamedTypeName(State);3192} else if (consumeIf("DC")) {3193// Structured binding3194size_t BindingsBegin = Names.size();3195do {3196Node *Binding = getDerived().parseSourceName(State);3197if (Binding == nullptr)3198return nullptr;3199Names.push_back(Binding);3200} while (!consumeIf('E'));3201Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));3202} else if (look() == 'C' || look() == 'D') {3203// A <ctor-dtor-name>.3204if (Scope == nullptr || Module != nullptr)3205return nullptr;3206Result = getDerived().parseCtorDtorName(Scope, State);3207} else {3208Result = getDerived().parseOperatorName(State);3209}32103211if (Result != nullptr && Module != nullptr)3212Result = make<ModuleEntity>(Module, Result);3213if (Result != nullptr)3214Result = getDerived().parseAbiTags(Result);3215if (Result != nullptr && IsMemberLikeFriend)3216Result = make<MemberLikeFriendName>(Scope, Result);3217else if (Result != nullptr && Scope != nullptr)3218Result = make<NestedName>(Scope, Result);32193220return Result;3221}32223223// <module-name> ::= <module-subname>3224// ::= <module-name> <module-subname>3225// ::= <substitution> # passed in by caller3226// <module-subname> ::= W <source-name>3227// ::= W P <source-name>3228template <typename Derived, typename Alloc>3229bool AbstractManglingParser<Derived, Alloc>::parseModuleNameOpt(3230ModuleName *&Module) {3231while (consumeIf('W')) {3232bool IsPartition = consumeIf('P');3233Node *Sub = getDerived().parseSourceName(nullptr);3234if (!Sub)3235return true;3236Module =3237static_cast<ModuleName *>(make<ModuleName>(Module, Sub, IsPartition));3238Subs.push_back(Module);3239}32403241return false;3242}32433244// <unnamed-type-name> ::= Ut [<nonnegative number>] _3245// ::= <closure-type-name>3246//3247// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _3248//3249// <lambda-sig> ::= <template-param-decl>* [Q <requires-clause expression>]3250// <parameter type>+ # or "v" if the lambda has no parameters3251template <typename Derived, typename Alloc>3252Node *3253AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *State) {3254// <template-params> refer to the innermost <template-args>. Clear out any3255// outer args that we may have inserted into TemplateParams.3256if (State != nullptr)3257TemplateParams.clear();32583259if (consumeIf("Ut")) {3260std::string_view Count = parseNumber();3261if (!consumeIf('_'))3262return nullptr;3263return make<UnnamedTypeName>(Count);3264}3265if (consumeIf("Ul")) {3266ScopedOverride<size_t> SwapParams(ParsingLambdaParamsAtLevel,3267TemplateParams.size());3268ScopedTemplateParamList LambdaTemplateParams(this);32693270size_t ParamsBegin = Names.size();3271while (getDerived().isTemplateParamDecl()) {3272Node *T =3273getDerived().parseTemplateParamDecl(LambdaTemplateParams.params());3274if (T == nullptr)3275return nullptr;3276Names.push_back(T);3277}3278NodeArray TempParams = popTrailingNodeArray(ParamsBegin);32793280// FIXME: If TempParams is empty and none of the function parameters3281// includes 'auto', we should remove LambdaTemplateParams from the3282// TemplateParams list. Unfortunately, we don't find out whether there are3283// any 'auto' parameters until too late in an example such as:3284//3285// template<typename T> void f(3286// decltype([](decltype([]<typename T>(T v) {}),3287// auto) {})) {}3288// template<typename T> void f(3289// decltype([](decltype([]<typename T>(T w) {}),3290// int) {})) {}3291//3292// Here, the type of v is at level 2 but the type of w is at level 1. We3293// don't find this out until we encounter the type of the next parameter.3294//3295// However, compilers can't actually cope with the former example in3296// practice, and it's likely to be made ill-formed in future, so we don't3297// need to support it here.3298//3299// If we encounter an 'auto' in the function parameter types, we will3300// recreate a template parameter scope for it, but any intervening lambdas3301// will be parsed in the 'wrong' template parameter depth.3302if (TempParams.empty())3303TemplateParams.pop_back();33043305Node *Requires1 = nullptr;3306if (consumeIf('Q')) {3307Requires1 = getDerived().parseConstraintExpr();3308if (Requires1 == nullptr)3309return nullptr;3310}33113312if (!consumeIf("v")) {3313do {3314Node *P = getDerived().parseType();3315if (P == nullptr)3316return nullptr;3317Names.push_back(P);3318} while (look() != 'E' && look() != 'Q');3319}3320NodeArray Params = popTrailingNodeArray(ParamsBegin);33213322Node *Requires2 = nullptr;3323if (consumeIf('Q')) {3324Requires2 = getDerived().parseConstraintExpr();3325if (Requires2 == nullptr)3326return nullptr;3327}33283329if (!consumeIf('E'))3330return nullptr;33313332std::string_view Count = parseNumber();3333if (!consumeIf('_'))3334return nullptr;3335return make<ClosureTypeName>(TempParams, Requires1, Params, Requires2,3336Count);3337}3338if (consumeIf("Ub")) {3339(void)parseNumber();3340if (!consumeIf('_'))3341return nullptr;3342return make<NameType>("'block-literal'");3343}3344return nullptr;3345}33463347// <source-name> ::= <positive length number> <identifier>3348template <typename Derived, typename Alloc>3349Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {3350size_t Length = 0;3351if (parsePositiveInteger(&Length))3352return nullptr;3353if (numLeft() < Length || Length == 0)3354return nullptr;3355std::string_view Name(First, Length);3356First += Length;3357if (starts_with(Name, "_GLOBAL__N"))3358return make<NameType>("(anonymous namespace)");3359return make<NameType>(Name);3360}33613362// Operator encodings3363template <typename Derived, typename Alloc>3364const typename AbstractManglingParser<3365Derived, Alloc>::OperatorInfo AbstractManglingParser<Derived,3366Alloc>::Ops[] = {3367// Keep ordered by encoding3368{"aN", OperatorInfo::Binary, false, Node::Prec::Assign, "operator&="},3369{"aS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator="},3370{"aa", OperatorInfo::Binary, false, Node::Prec::AndIf, "operator&&"},3371{"ad", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator&"},3372{"an", OperatorInfo::Binary, false, Node::Prec::And, "operator&"},3373{"at", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "alignof "},3374{"aw", OperatorInfo::NameOnly, false, Node::Prec::Primary,3375"operator co_await"},3376{"az", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "alignof "},3377{"cc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "const_cast"},3378{"cl", OperatorInfo::Call, /*Paren*/ false, Node::Prec::Postfix,3379"operator()"},3380{"cm", OperatorInfo::Binary, false, Node::Prec::Comma, "operator,"},3381{"co", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator~"},3382{"cp", OperatorInfo::Call, /*Paren*/ true, Node::Prec::Postfix,3383"operator()"},3384{"cv", OperatorInfo::CCast, false, Node::Prec::Cast, "operator"}, // C Cast3385{"dV", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/="},3386{"da", OperatorInfo::Del, /*Ary*/ true, Node::Prec::Unary,3387"operator delete[]"},3388{"dc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "dynamic_cast"},3389{"de", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator*"},3390{"dl", OperatorInfo::Del, /*Ary*/ false, Node::Prec::Unary,3391"operator delete"},3392{"ds", OperatorInfo::Member, /*Named*/ false, Node::Prec::PtrMem,3393"operator.*"},3394{"dt", OperatorInfo::Member, /*Named*/ false, Node::Prec::Postfix,3395"operator."},3396{"dv", OperatorInfo::Binary, false, Node::Prec::Assign, "operator/"},3397{"eO", OperatorInfo::Binary, false, Node::Prec::Assign, "operator^="},3398{"eo", OperatorInfo::Binary, false, Node::Prec::Xor, "operator^"},3399{"eq", OperatorInfo::Binary, false, Node::Prec::Equality, "operator=="},3400{"ge", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>="},3401{"gt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator>"},3402{"ix", OperatorInfo::Array, false, Node::Prec::Postfix, "operator[]"},3403{"lS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator<<="},3404{"le", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<="},3405{"ls", OperatorInfo::Binary, false, Node::Prec::Shift, "operator<<"},3406{"lt", OperatorInfo::Binary, false, Node::Prec::Relational, "operator<"},3407{"mI", OperatorInfo::Binary, false, Node::Prec::Assign, "operator-="},3408{"mL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator*="},3409{"mi", OperatorInfo::Binary, false, Node::Prec::Additive, "operator-"},3410{"ml", OperatorInfo::Binary, false, Node::Prec::Multiplicative,3411"operator*"},3412{"mm", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator--"},3413{"na", OperatorInfo::New, /*Ary*/ true, Node::Prec::Unary,3414"operator new[]"},3415{"ne", OperatorInfo::Binary, false, Node::Prec::Equality, "operator!="},3416{"ng", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator-"},3417{"nt", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator!"},3418{"nw", OperatorInfo::New, /*Ary*/ false, Node::Prec::Unary, "operator new"},3419{"oR", OperatorInfo::Binary, false, Node::Prec::Assign, "operator|="},3420{"oo", OperatorInfo::Binary, false, Node::Prec::OrIf, "operator||"},3421{"or", OperatorInfo::Binary, false, Node::Prec::Ior, "operator|"},3422{"pL", OperatorInfo::Binary, false, Node::Prec::Assign, "operator+="},3423{"pl", OperatorInfo::Binary, false, Node::Prec::Additive, "operator+"},3424{"pm", OperatorInfo::Member, /*Named*/ true, Node::Prec::PtrMem,3425"operator->*"},3426{"pp", OperatorInfo::Postfix, false, Node::Prec::Postfix, "operator++"},3427{"ps", OperatorInfo::Prefix, false, Node::Prec::Unary, "operator+"},3428{"pt", OperatorInfo::Member, /*Named*/ true, Node::Prec::Postfix,3429"operator->"},3430{"qu", OperatorInfo::Conditional, false, Node::Prec::Conditional,3431"operator?"},3432{"rM", OperatorInfo::Binary, false, Node::Prec::Assign, "operator%="},3433{"rS", OperatorInfo::Binary, false, Node::Prec::Assign, "operator>>="},3434{"rc", OperatorInfo::NamedCast, false, Node::Prec::Postfix,3435"reinterpret_cast"},3436{"rm", OperatorInfo::Binary, false, Node::Prec::Multiplicative,3437"operator%"},3438{"rs", OperatorInfo::Binary, false, Node::Prec::Shift, "operator>>"},3439{"sc", OperatorInfo::NamedCast, false, Node::Prec::Postfix, "static_cast"},3440{"ss", OperatorInfo::Binary, false, Node::Prec::Spaceship, "operator<=>"},3441{"st", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Unary, "sizeof "},3442{"sz", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Unary, "sizeof "},3443{"te", OperatorInfo::OfIdOp, /*Type*/ false, Node::Prec::Postfix,3444"typeid "},3445{"ti", OperatorInfo::OfIdOp, /*Type*/ true, Node::Prec::Postfix, "typeid "},3446};3447template <typename Derived, typename Alloc>3448const size_t AbstractManglingParser<Derived, Alloc>::NumOps = sizeof(Ops) /3449sizeof(Ops[0]);34503451// If the next 2 chars are an operator encoding, consume them and return their3452// OperatorInfo. Otherwise return nullptr.3453template <typename Derived, typename Alloc>3454const typename AbstractManglingParser<Derived, Alloc>::OperatorInfo *3455AbstractManglingParser<Derived, Alloc>::parseOperatorEncoding() {3456if (numLeft() < 2)3457return nullptr;34583459// We can't use lower_bound as that can link to symbols in the C++ library,3460// and this must remain independent of that.3461size_t lower = 0u, upper = NumOps - 1; // Inclusive bounds.3462while (upper != lower) {3463size_t middle = (upper + lower) / 2;3464if (Ops[middle] < First)3465lower = middle + 1;3466else3467upper = middle;3468}3469if (Ops[lower] != First)3470return nullptr;34713472First += 2;3473return &Ops[lower];3474}34753476// <operator-name> ::= See parseOperatorEncoding()3477// ::= li <source-name> # operator ""3478// ::= v <digit> <source-name> # vendor extended operator3479template <typename Derived, typename Alloc>3480Node *3481AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {3482if (const auto *Op = parseOperatorEncoding()) {3483if (Op->getKind() == OperatorInfo::CCast) {3484// ::= cv <type> # (cast)3485ScopedOverride<bool> SaveTemplate(TryToParseTemplateArgs, false);3486// If we're parsing an encoding, State != nullptr and the conversion3487// operators' <type> could have a <template-param> that refers to some3488// <template-arg>s further ahead in the mangled name.3489ScopedOverride<bool> SavePermit(PermitForwardTemplateReferences,3490PermitForwardTemplateReferences ||3491State != nullptr);3492Node *Ty = getDerived().parseType();3493if (Ty == nullptr)3494return nullptr;3495if (State) State->CtorDtorConversion = true;3496return make<ConversionOperatorType>(Ty);3497}34983499if (Op->getKind() >= OperatorInfo::Unnameable)3500/* Not a nameable operator. */3501return nullptr;3502if (Op->getKind() == OperatorInfo::Member && !Op->getFlag())3503/* Not a nameable MemberExpr */3504return nullptr;35053506return make<NameType>(Op->getName());3507}35083509if (consumeIf("li")) {3510// ::= li <source-name> # operator ""3511Node *SN = getDerived().parseSourceName(State);3512if (SN == nullptr)3513return nullptr;3514return make<LiteralOperator>(SN);3515}35163517if (consumeIf('v')) {3518// ::= v <digit> <source-name> # vendor extended operator3519if (look() >= '0' && look() <= '9') {3520First++;3521Node *SN = getDerived().parseSourceName(State);3522if (SN == nullptr)3523return nullptr;3524return make<ConversionOperatorType>(SN);3525}3526return nullptr;3527}35283529return nullptr;3530}35313532// <ctor-dtor-name> ::= C1 # complete object constructor3533// ::= C2 # base object constructor3534// ::= C3 # complete object allocating constructor3535// extension ::= C4 # gcc old-style "[unified]" constructor3536// extension ::= C5 # the COMDAT used for ctors3537// ::= D0 # deleting destructor3538// ::= D1 # complete object destructor3539// ::= D2 # base object destructor3540// extension ::= D4 # gcc old-style "[unified]" destructor3541// extension ::= D5 # the COMDAT used for dtors3542template <typename Derived, typename Alloc>3543Node *3544AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,3545NameState *State) {3546if (SoFar->getKind() == Node::KSpecialSubstitution) {3547// Expand the special substitution.3548SoFar = make<ExpandedSpecialSubstitution>(3549static_cast<SpecialSubstitution *>(SoFar));3550if (!SoFar)3551return nullptr;3552}35533554if (consumeIf('C')) {3555bool IsInherited = consumeIf('I');3556if (look() != '1' && look() != '2' && look() != '3' && look() != '4' &&3557look() != '5')3558return nullptr;3559int Variant = look() - '0';3560++First;3561if (State) State->CtorDtorConversion = true;3562if (IsInherited) {3563if (getDerived().parseName(State) == nullptr)3564return nullptr;3565}3566return make<CtorDtorName>(SoFar, /*IsDtor=*/false, Variant);3567}35683569if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' ||3570look(1) == '4' || look(1) == '5')) {3571int Variant = look(1) - '0';3572First += 2;3573if (State) State->CtorDtorConversion = true;3574return make<CtorDtorName>(SoFar, /*IsDtor=*/true, Variant);3575}35763577return nullptr;3578}35793580// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix>3581// <unqualified-name> E3582// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix>3583// <template-args> E3584//3585// <prefix> ::= <prefix> <unqualified-name>3586// ::= <template-prefix> <template-args>3587// ::= <template-param>3588// ::= <decltype>3589// ::= # empty3590// ::= <substitution>3591// ::= <prefix> <data-member-prefix>3592// [*] extension3593//3594// <data-member-prefix> := <member source-name> [<template-args>] M3595//3596// <template-prefix> ::= <prefix> <template unqualified-name>3597// ::= <template-param>3598// ::= <substitution>3599template <typename Derived, typename Alloc>3600Node *3601AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {3602if (!consumeIf('N'))3603return nullptr;36043605// 'H' specifies that the encoding that follows3606// has an explicit object parameter.3607if (!consumeIf('H')) {3608Qualifiers CVTmp = parseCVQualifiers();3609if (State)3610State->CVQualifiers = CVTmp;36113612if (consumeIf('O')) {3613if (State)3614State->ReferenceQualifier = FrefQualRValue;3615} else if (consumeIf('R')) {3616if (State)3617State->ReferenceQualifier = FrefQualLValue;3618} else {3619if (State)3620State->ReferenceQualifier = FrefQualNone;3621}3622} else if (State) {3623State->HasExplicitObjectParameter = true;3624}36253626Node *SoFar = nullptr;3627while (!consumeIf('E')) {3628if (State)3629// Only set end-with-template on the case that does that.3630State->EndsWithTemplateArgs = false;36313632if (look() == 'T') {3633// ::= <template-param>3634if (SoFar != nullptr)3635return nullptr; // Cannot have a prefix.3636SoFar = getDerived().parseTemplateParam();3637} else if (look() == 'I') {3638// ::= <template-prefix> <template-args>3639if (SoFar == nullptr)3640return nullptr; // Must have a prefix.3641Node *TA = getDerived().parseTemplateArgs(State != nullptr);3642if (TA == nullptr)3643return nullptr;3644if (SoFar->getKind() == Node::KNameWithTemplateArgs)3645// Semantically <template-args> <template-args> cannot be generated by a3646// C++ entity. There will always be [something like] a name between3647// them.3648return nullptr;3649if (State)3650State->EndsWithTemplateArgs = true;3651SoFar = make<NameWithTemplateArgs>(SoFar, TA);3652} else if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {3653// ::= <decltype>3654if (SoFar != nullptr)3655return nullptr; // Cannot have a prefix.3656SoFar = getDerived().parseDecltype();3657} else {3658ModuleName *Module = nullptr;36593660if (look() == 'S') {3661// ::= <substitution>3662Node *S = nullptr;3663if (look(1) == 't') {3664First += 2;3665S = make<NameType>("std");3666} else {3667S = getDerived().parseSubstitution();3668}3669if (!S)3670return nullptr;3671if (S->getKind() == Node::KModuleName) {3672Module = static_cast<ModuleName *>(S);3673} else if (SoFar != nullptr) {3674return nullptr; // Cannot have a prefix.3675} else {3676SoFar = S;3677continue; // Do not push a new substitution.3678}3679}36803681// ::= [<prefix>] <unqualified-name>3682SoFar = getDerived().parseUnqualifiedName(State, SoFar, Module);3683}36843685if (SoFar == nullptr)3686return nullptr;3687Subs.push_back(SoFar);36883689// No longer used.3690// <data-member-prefix> := <member source-name> [<template-args>] M3691consumeIf('M');3692}36933694if (SoFar == nullptr || Subs.empty())3695return nullptr;36963697Subs.pop_back();3698return SoFar;3699}37003701// <simple-id> ::= <source-name> [ <template-args> ]3702template <typename Derived, typename Alloc>3703Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {3704Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);3705if (SN == nullptr)3706return nullptr;3707if (look() == 'I') {3708Node *TA = getDerived().parseTemplateArgs();3709if (TA == nullptr)3710return nullptr;3711return make<NameWithTemplateArgs>(SN, TA);3712}3713return SN;3714}37153716// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())3717// ::= <simple-id> # e.g., ~A<2*N>3718template <typename Derived, typename Alloc>3719Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {3720Node *Result;3721if (std::isdigit(look()))3722Result = getDerived().parseSimpleId();3723else3724Result = getDerived().parseUnresolvedType();3725if (Result == nullptr)3726return nullptr;3727return make<DtorName>(Result);3728}37293730// <unresolved-type> ::= <template-param>3731// ::= <decltype>3732// ::= <substitution>3733template <typename Derived, typename Alloc>3734Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {3735if (look() == 'T') {3736Node *TP = getDerived().parseTemplateParam();3737if (TP == nullptr)3738return nullptr;3739Subs.push_back(TP);3740return TP;3741}3742if (look() == 'D') {3743Node *DT = getDerived().parseDecltype();3744if (DT == nullptr)3745return nullptr;3746Subs.push_back(DT);3747return DT;3748}3749return getDerived().parseSubstitution();3750}37513752// <base-unresolved-name> ::= <simple-id> # unresolved name3753// extension ::= <operator-name> # unresolved operator-function-id3754// extension ::= <operator-name> <template-args> # unresolved operator template-id3755// ::= on <operator-name> # unresolved operator-function-id3756// ::= on <operator-name> <template-args> # unresolved operator template-id3757// ::= dn <destructor-name> # destructor or pseudo-destructor;3758// # e.g. ~X or ~X<N-1>3759template <typename Derived, typename Alloc>3760Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {3761if (std::isdigit(look()))3762return getDerived().parseSimpleId();37633764if (consumeIf("dn"))3765return getDerived().parseDestructorName();37663767consumeIf("on");37683769Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);3770if (Oper == nullptr)3771return nullptr;3772if (look() == 'I') {3773Node *TA = getDerived().parseTemplateArgs();3774if (TA == nullptr)3775return nullptr;3776return make<NameWithTemplateArgs>(Oper, TA);3777}3778return Oper;3779}37803781// <unresolved-name>3782// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3783// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x3784// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3785// # A::x, N::y, A<T>::z; "gs" means leading "::"3786// [gs] has been parsed by caller.3787// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x3788// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>3789// # T::N::x /decltype(p)::N::x3790// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3791//3792// <unresolved-qualifier-level> ::= <simple-id>3793template <typename Derived, typename Alloc>3794Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName(bool Global) {3795Node *SoFar = nullptr;37963797// srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3798// srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3799if (consumeIf("srN")) {3800SoFar = getDerived().parseUnresolvedType();3801if (SoFar == nullptr)3802return nullptr;38033804if (look() == 'I') {3805Node *TA = getDerived().parseTemplateArgs();3806if (TA == nullptr)3807return nullptr;3808SoFar = make<NameWithTemplateArgs>(SoFar, TA);3809if (!SoFar)3810return nullptr;3811}38123813while (!consumeIf('E')) {3814Node *Qual = getDerived().parseSimpleId();3815if (Qual == nullptr)3816return nullptr;3817SoFar = make<QualifiedName>(SoFar, Qual);3818if (!SoFar)3819return nullptr;3820}38213822Node *Base = getDerived().parseBaseUnresolvedName();3823if (Base == nullptr)3824return nullptr;3825return make<QualifiedName>(SoFar, Base);3826}38273828// [gs] <base-unresolved-name> # x or (with "gs") ::x3829if (!consumeIf("sr")) {3830SoFar = getDerived().parseBaseUnresolvedName();3831if (SoFar == nullptr)3832return nullptr;3833if (Global)3834SoFar = make<GlobalQualifiedName>(SoFar);3835return SoFar;3836}38373838// [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3839if (std::isdigit(look())) {3840do {3841Node *Qual = getDerived().parseSimpleId();3842if (Qual == nullptr)3843return nullptr;3844if (SoFar)3845SoFar = make<QualifiedName>(SoFar, Qual);3846else if (Global)3847SoFar = make<GlobalQualifiedName>(Qual);3848else3849SoFar = Qual;3850if (!SoFar)3851return nullptr;3852} while (!consumeIf('E'));3853}3854// sr <unresolved-type> <base-unresolved-name>3855// sr <unresolved-type> <template-args> <base-unresolved-name>3856else {3857SoFar = getDerived().parseUnresolvedType();3858if (SoFar == nullptr)3859return nullptr;38603861if (look() == 'I') {3862Node *TA = getDerived().parseTemplateArgs();3863if (TA == nullptr)3864return nullptr;3865SoFar = make<NameWithTemplateArgs>(SoFar, TA);3866if (!SoFar)3867return nullptr;3868}3869}38703871DEMANGLE_ASSERT(SoFar != nullptr, "");38723873Node *Base = getDerived().parseBaseUnresolvedName();3874if (Base == nullptr)3875return nullptr;3876return make<QualifiedName>(SoFar, Base);3877}38783879// <abi-tags> ::= <abi-tag> [<abi-tags>]3880// <abi-tag> ::= B <source-name>3881template <typename Derived, typename Alloc>3882Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {3883while (consumeIf('B')) {3884std::string_view SN = parseBareSourceName();3885if (SN.empty())3886return nullptr;3887N = make<AbiTagAttr>(N, SN);3888if (!N)3889return nullptr;3890}3891return N;3892}38933894// <number> ::= [n] <non-negative decimal integer>3895template <typename Alloc, typename Derived>3896std::string_view3897AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {3898const char *Tmp = First;3899if (AllowNegative)3900consumeIf('n');3901if (numLeft() == 0 || !std::isdigit(*First))3902return std::string_view();3903while (numLeft() != 0 && std::isdigit(*First))3904++First;3905return std::string_view(Tmp, First - Tmp);3906}39073908// <positive length number> ::= [0-9]*3909template <typename Alloc, typename Derived>3910bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {3911*Out = 0;3912if (look() < '0' || look() > '9')3913return true;3914while (look() >= '0' && look() <= '9') {3915*Out *= 10;3916*Out += static_cast<size_t>(consume() - '0');3917}3918return false;3919}39203921template <typename Alloc, typename Derived>3922std::string_view AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {3923size_t Int = 0;3924if (parsePositiveInteger(&Int) || numLeft() < Int)3925return {};3926std::string_view R(First, Int);3927First += Int;3928return R;3929}39303931// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E3932//3933// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())3934// ::= DO <expression> E # computed (instantiation-dependent) noexcept3935// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types3936//3937// <ref-qualifier> ::= R # & ref-qualifier3938// <ref-qualifier> ::= O # && ref-qualifier3939template <typename Derived, typename Alloc>3940Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {3941Qualifiers CVQuals = parseCVQualifiers();39423943Node *ExceptionSpec = nullptr;3944if (consumeIf("Do")) {3945ExceptionSpec = make<NameType>("noexcept");3946if (!ExceptionSpec)3947return nullptr;3948} else if (consumeIf("DO")) {3949Node *E = getDerived().parseExpr();3950if (E == nullptr || !consumeIf('E'))3951return nullptr;3952ExceptionSpec = make<NoexceptSpec>(E);3953if (!ExceptionSpec)3954return nullptr;3955} else if (consumeIf("Dw")) {3956size_t SpecsBegin = Names.size();3957while (!consumeIf('E')) {3958Node *T = getDerived().parseType();3959if (T == nullptr)3960return nullptr;3961Names.push_back(T);3962}3963ExceptionSpec =3964make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));3965if (!ExceptionSpec)3966return nullptr;3967}39683969consumeIf("Dx"); // transaction safe39703971if (!consumeIf('F'))3972return nullptr;3973consumeIf('Y'); // extern "C"3974Node *ReturnType = getDerived().parseType();3975if (ReturnType == nullptr)3976return nullptr;39773978FunctionRefQual ReferenceQualifier = FrefQualNone;3979size_t ParamsBegin = Names.size();3980while (true) {3981if (consumeIf('E'))3982break;3983if (consumeIf('v'))3984continue;3985if (consumeIf("RE")) {3986ReferenceQualifier = FrefQualLValue;3987break;3988}3989if (consumeIf("OE")) {3990ReferenceQualifier = FrefQualRValue;3991break;3992}3993Node *T = getDerived().parseType();3994if (T == nullptr)3995return nullptr;3996Names.push_back(T);3997}39983999NodeArray Params = popTrailingNodeArray(ParamsBegin);4000return make<FunctionType>(ReturnType, Params, CVQuals,4001ReferenceQualifier, ExceptionSpec);4002}40034004// extension:4005// <vector-type> ::= Dv <positive dimension number> _ <extended element type>4006// ::= Dv [<dimension expression>] _ <element type>4007// <extended element type> ::= <element type>4008// ::= p # AltiVec vector pixel4009template <typename Derived, typename Alloc>4010Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {4011if (!consumeIf("Dv"))4012return nullptr;4013if (look() >= '1' && look() <= '9') {4014Node *DimensionNumber = make<NameType>(parseNumber());4015if (!DimensionNumber)4016return nullptr;4017if (!consumeIf('_'))4018return nullptr;4019if (consumeIf('p'))4020return make<PixelVectorType>(DimensionNumber);4021Node *ElemType = getDerived().parseType();4022if (ElemType == nullptr)4023return nullptr;4024return make<VectorType>(ElemType, DimensionNumber);4025}40264027if (!consumeIf('_')) {4028Node *DimExpr = getDerived().parseExpr();4029if (!DimExpr)4030return nullptr;4031if (!consumeIf('_'))4032return nullptr;4033Node *ElemType = getDerived().parseType();4034if (!ElemType)4035return nullptr;4036return make<VectorType>(ElemType, DimExpr);4037}4038Node *ElemType = getDerived().parseType();4039if (!ElemType)4040return nullptr;4041return make<VectorType>(ElemType, /*Dimension=*/nullptr);4042}40434044// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)4045// ::= DT <expression> E # decltype of an expression (C++0x)4046template <typename Derived, typename Alloc>4047Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {4048if (!consumeIf('D'))4049return nullptr;4050if (!consumeIf('t') && !consumeIf('T'))4051return nullptr;4052Node *E = getDerived().parseExpr();4053if (E == nullptr)4054return nullptr;4055if (!consumeIf('E'))4056return nullptr;4057return make<EnclosingExpr>("decltype", E);4058}40594060// <array-type> ::= A <positive dimension number> _ <element type>4061// ::= A [<dimension expression>] _ <element type>4062template <typename Derived, typename Alloc>4063Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {4064if (!consumeIf('A'))4065return nullptr;40664067Node *Dimension = nullptr;40684069if (std::isdigit(look())) {4070Dimension = make<NameType>(parseNumber());4071if (!Dimension)4072return nullptr;4073if (!consumeIf('_'))4074return nullptr;4075} else if (!consumeIf('_')) {4076Node *DimExpr = getDerived().parseExpr();4077if (DimExpr == nullptr)4078return nullptr;4079if (!consumeIf('_'))4080return nullptr;4081Dimension = DimExpr;4082}40834084Node *Ty = getDerived().parseType();4085if (Ty == nullptr)4086return nullptr;4087return make<ArrayType>(Ty, Dimension);4088}40894090// <pointer-to-member-type> ::= M <class type> <member type>4091template <typename Derived, typename Alloc>4092Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {4093if (!consumeIf('M'))4094return nullptr;4095Node *ClassType = getDerived().parseType();4096if (ClassType == nullptr)4097return nullptr;4098Node *MemberType = getDerived().parseType();4099if (MemberType == nullptr)4100return nullptr;4101return make<PointerToMemberType>(ClassType, MemberType);4102}41034104// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier4105// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'4106// ::= Tu <name> # dependent elaborated type specifier using 'union'4107// ::= Te <name> # dependent elaborated type specifier using 'enum'4108template <typename Derived, typename Alloc>4109Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {4110std::string_view ElabSpef;4111if (consumeIf("Ts"))4112ElabSpef = "struct";4113else if (consumeIf("Tu"))4114ElabSpef = "union";4115else if (consumeIf("Te"))4116ElabSpef = "enum";41174118Node *Name = getDerived().parseName();4119if (Name == nullptr)4120return nullptr;41214122if (!ElabSpef.empty())4123return make<ElaboratedTypeSpefType>(ElabSpef, Name);41244125return Name;4126}41274128// <qualified-type> ::= <qualifiers> <type>4129// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>4130// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier4131template <typename Derived, typename Alloc>4132Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {4133if (consumeIf('U')) {4134std::string_view Qual = parseBareSourceName();4135if (Qual.empty())4136return nullptr;41374138// extension ::= U <objc-name> <objc-type> # objc-type<identifier>4139if (starts_with(Qual, "objcproto")) {4140constexpr size_t Len = sizeof("objcproto") - 1;4141std::string_view ProtoSourceName(Qual.data() + Len, Qual.size() - Len);4142std::string_view Proto;4143{4144ScopedOverride<const char *> SaveFirst(First, ProtoSourceName.data()),4145SaveLast(Last, &*ProtoSourceName.rbegin() + 1);4146Proto = parseBareSourceName();4147}4148if (Proto.empty())4149return nullptr;4150Node *Child = getDerived().parseQualifiedType();4151if (Child == nullptr)4152return nullptr;4153return make<ObjCProtoName>(Child, Proto);4154}41554156Node *TA = nullptr;4157if (look() == 'I') {4158TA = getDerived().parseTemplateArgs();4159if (TA == nullptr)4160return nullptr;4161}41624163Node *Child = getDerived().parseQualifiedType();4164if (Child == nullptr)4165return nullptr;4166return make<VendorExtQualType>(Child, Qual, TA);4167}41684169Qualifiers Quals = parseCVQualifiers();4170Node *Ty = getDerived().parseType();4171if (Ty == nullptr)4172return nullptr;4173if (Quals != QualNone)4174Ty = make<QualType>(Ty, Quals);4175return Ty;4176}41774178// <type> ::= <builtin-type>4179// ::= <qualified-type>4180// ::= <function-type>4181// ::= <class-enum-type>4182// ::= <array-type>4183// ::= <pointer-to-member-type>4184// ::= <template-param>4185// ::= <template-template-param> <template-args>4186// ::= <decltype>4187// ::= P <type> # pointer4188// ::= R <type> # l-value reference4189// ::= O <type> # r-value reference (C++11)4190// ::= C <type> # complex pair (C99)4191// ::= G <type> # imaginary (C99)4192// ::= <substitution> # See Compression below4193// extension ::= U <objc-name> <objc-type> # objc-type<identifier>4194// extension ::= <vector-type> # <vector-type> starts with Dv4195//4196// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k14197// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>4198template <typename Derived, typename Alloc>4199Node *AbstractManglingParser<Derived, Alloc>::parseType() {4200Node *Result = nullptr;42014202switch (look()) {4203// ::= <qualified-type>4204case 'r':4205case 'V':4206case 'K': {4207unsigned AfterQuals = 0;4208if (look(AfterQuals) == 'r') ++AfterQuals;4209if (look(AfterQuals) == 'V') ++AfterQuals;4210if (look(AfterQuals) == 'K') ++AfterQuals;42114212if (look(AfterQuals) == 'F' ||4213(look(AfterQuals) == 'D' &&4214(look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||4215look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {4216Result = getDerived().parseFunctionType();4217break;4218}4219DEMANGLE_FALLTHROUGH;4220}4221case 'U': {4222Result = getDerived().parseQualifiedType();4223break;4224}4225// <builtin-type> ::= v # void4226case 'v':4227++First;4228return make<NameType>("void");4229// ::= w # wchar_t4230case 'w':4231++First;4232return make<NameType>("wchar_t");4233// ::= b # bool4234case 'b':4235++First;4236return make<NameType>("bool");4237// ::= c # char4238case 'c':4239++First;4240return make<NameType>("char");4241// ::= a # signed char4242case 'a':4243++First;4244return make<NameType>("signed char");4245// ::= h # unsigned char4246case 'h':4247++First;4248return make<NameType>("unsigned char");4249// ::= s # short4250case 's':4251++First;4252return make<NameType>("short");4253// ::= t # unsigned short4254case 't':4255++First;4256return make<NameType>("unsigned short");4257// ::= i # int4258case 'i':4259++First;4260return make<NameType>("int");4261// ::= j # unsigned int4262case 'j':4263++First;4264return make<NameType>("unsigned int");4265// ::= l # long4266case 'l':4267++First;4268return make<NameType>("long");4269// ::= m # unsigned long4270case 'm':4271++First;4272return make<NameType>("unsigned long");4273// ::= x # long long, __int644274case 'x':4275++First;4276return make<NameType>("long long");4277// ::= y # unsigned long long, __int644278case 'y':4279++First;4280return make<NameType>("unsigned long long");4281// ::= n # __int1284282case 'n':4283++First;4284return make<NameType>("__int128");4285// ::= o # unsigned __int1284286case 'o':4287++First;4288return make<NameType>("unsigned __int128");4289// ::= f # float4290case 'f':4291++First;4292return make<NameType>("float");4293// ::= d # double4294case 'd':4295++First;4296return make<NameType>("double");4297// ::= e # long double, __float804298case 'e':4299++First;4300return make<NameType>("long double");4301// ::= g # __float1284302case 'g':4303++First;4304return make<NameType>("__float128");4305// ::= z # ellipsis4306case 'z':4307++First;4308return make<NameType>("...");43094310// <builtin-type> ::= u <source-name> # vendor extended type4311case 'u': {4312++First;4313std::string_view Res = parseBareSourceName();4314if (Res.empty())4315return nullptr;4316// Typically, <builtin-type>s are not considered substitution candidates,4317// but the exception to that exception is vendor extended types (Itanium C++4318// ABI 5.9.1).4319if (consumeIf('I')) {4320Node *BaseType = parseType();4321if (BaseType == nullptr)4322return nullptr;4323if (!consumeIf('E'))4324return nullptr;4325Result = make<TransformedType>(Res, BaseType);4326} else4327Result = make<NameType>(Res);4328break;4329}4330case 'D':4331switch (look(1)) {4332// ::= Dd # IEEE 754r decimal floating point (64 bits)4333case 'd':4334First += 2;4335return make<NameType>("decimal64");4336// ::= De # IEEE 754r decimal floating point (128 bits)4337case 'e':4338First += 2;4339return make<NameType>("decimal128");4340// ::= Df # IEEE 754r decimal floating point (32 bits)4341case 'f':4342First += 2;4343return make<NameType>("decimal32");4344// ::= Dh # IEEE 754r half-precision floating point (16 bits)4345case 'h':4346First += 2;4347return make<NameType>("half");4348// ::= DF16b # C++23 std::bfloat16_t4349// ::= DF <number> _ # ISO/IEC TS 18661 binary floating point (N bits)4350case 'F': {4351First += 2;4352if (consumeIf("16b"))4353return make<NameType>("std::bfloat16_t");4354Node *DimensionNumber = make<NameType>(parseNumber());4355if (!DimensionNumber)4356return nullptr;4357if (!consumeIf('_'))4358return nullptr;4359return make<BinaryFPType>(DimensionNumber);4360}4361// ::= [DS] DA # N1169 fixed-point [_Sat] T _Accum4362// ::= [DS] DR # N1169 fixed-point [_Sat] T _Frac4363// <fixed-point-size>4364// ::= s # short4365// ::= t # unsigned short4366// ::= i # plain4367// ::= j # unsigned4368// ::= l # long4369// ::= m # unsigned long4370case 'A': {4371char c = look(2);4372First += 3;4373switch (c) {4374case 's':4375return make<NameType>("short _Accum");4376case 't':4377return make<NameType>("unsigned short _Accum");4378case 'i':4379return make<NameType>("_Accum");4380case 'j':4381return make<NameType>("unsigned _Accum");4382case 'l':4383return make<NameType>("long _Accum");4384case 'm':4385return make<NameType>("unsigned long _Accum");4386default:4387return nullptr;4388}4389}4390case 'R': {4391char c = look(2);4392First += 3;4393switch (c) {4394case 's':4395return make<NameType>("short _Fract");4396case 't':4397return make<NameType>("unsigned short _Fract");4398case 'i':4399return make<NameType>("_Fract");4400case 'j':4401return make<NameType>("unsigned _Fract");4402case 'l':4403return make<NameType>("long _Fract");4404case 'm':4405return make<NameType>("unsigned long _Fract");4406default:4407return nullptr;4408}4409}4410case 'S': {4411First += 2;4412if (look() != 'D')4413return nullptr;4414if (look(1) == 'A') {4415char c = look(2);4416First += 3;4417switch (c) {4418case 's':4419return make<NameType>("_Sat short _Accum");4420case 't':4421return make<NameType>("_Sat unsigned short _Accum");4422case 'i':4423return make<NameType>("_Sat _Accum");4424case 'j':4425return make<NameType>("_Sat unsigned _Accum");4426case 'l':4427return make<NameType>("_Sat long _Accum");4428case 'm':4429return make<NameType>("_Sat unsigned long _Accum");4430default:4431return nullptr;4432}4433}4434if (look(1) == 'R') {4435char c = look(2);4436First += 3;4437switch (c) {4438case 's':4439return make<NameType>("_Sat short _Fract");4440case 't':4441return make<NameType>("_Sat unsigned short _Fract");4442case 'i':4443return make<NameType>("_Sat _Fract");4444case 'j':4445return make<NameType>("_Sat unsigned _Fract");4446case 'l':4447return make<NameType>("_Sat long _Fract");4448case 'm':4449return make<NameType>("_Sat unsigned long _Fract");4450default:4451return nullptr;4452}4453}4454return nullptr;4455}4456// ::= DB <number> _ # C23 signed _BitInt(N)4457// ::= DB <instantiation-dependent expression> _ # C23 signed _BitInt(N)4458// ::= DU <number> _ # C23 unsigned _BitInt(N)4459// ::= DU <instantiation-dependent expression> _ # C23 unsigned _BitInt(N)4460case 'B':4461case 'U': {4462bool Signed = look(1) == 'B';4463First += 2;4464Node *Size = std::isdigit(look()) ? make<NameType>(parseNumber())4465: getDerived().parseExpr();4466if (!Size)4467return nullptr;4468if (!consumeIf('_'))4469return nullptr;4470// The front end expects this to be available for Substitution4471Result = make<BitIntType>(Size, Signed);4472break;4473}4474// ::= Di # char32_t4475case 'i':4476First += 2;4477return make<NameType>("char32_t");4478// ::= Ds # char16_t4479case 's':4480First += 2;4481return make<NameType>("char16_t");4482// ::= Du # char8_t (C++2a, not yet in the Itanium spec)4483case 'u':4484First += 2;4485return make<NameType>("char8_t");4486// ::= Da # auto (in dependent new-expressions)4487case 'a':4488First += 2;4489return make<NameType>("auto");4490// ::= Dc # decltype(auto)4491case 'c':4492First += 2;4493return make<NameType>("decltype(auto)");4494// ::= Dk <type-constraint> # constrained auto4495// ::= DK <type-constraint> # constrained decltype(auto)4496case 'k':4497case 'K': {4498std::string_view Kind = look(1) == 'k' ? " auto" : " decltype(auto)";4499First += 2;4500Node *Constraint = getDerived().parseName();4501if (!Constraint)4502return nullptr;4503return make<PostfixQualifiedType>(Constraint, Kind);4504}4505// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))4506case 'n':4507First += 2;4508return make<NameType>("std::nullptr_t");45094510// ::= <decltype>4511case 't':4512case 'T': {4513Result = getDerived().parseDecltype();4514break;4515}4516// extension ::= <vector-type> # <vector-type> starts with Dv4517case 'v': {4518Result = getDerived().parseVectorType();4519break;4520}4521// ::= Dp <type> # pack expansion (C++0x)4522case 'p': {4523First += 2;4524Node *Child = getDerived().parseType();4525if (!Child)4526return nullptr;4527Result = make<ParameterPackExpansion>(Child);4528break;4529}4530// Exception specifier on a function type.4531case 'o':4532case 'O':4533case 'w':4534// Transaction safe function type.4535case 'x':4536Result = getDerived().parseFunctionType();4537break;4538}4539break;4540// ::= <function-type>4541case 'F': {4542Result = getDerived().parseFunctionType();4543break;4544}4545// ::= <array-type>4546case 'A': {4547Result = getDerived().parseArrayType();4548break;4549}4550// ::= <pointer-to-member-type>4551case 'M': {4552Result = getDerived().parsePointerToMemberType();4553break;4554}4555// ::= <template-param>4556case 'T': {4557// This could be an elaborate type specifier on a <class-enum-type>.4558if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {4559Result = getDerived().parseClassEnumType();4560break;4561}45624563Result = getDerived().parseTemplateParam();4564if (Result == nullptr)4565return nullptr;45664567// Result could be either of:4568// <type> ::= <template-param>4569// <type> ::= <template-template-param> <template-args>4570//4571// <template-template-param> ::= <template-param>4572// ::= <substitution>4573//4574// If this is followed by some <template-args>, and we're permitted to4575// parse them, take the second production.45764577if (TryToParseTemplateArgs && look() == 'I') {4578Subs.push_back(Result);4579Node *TA = getDerived().parseTemplateArgs();4580if (TA == nullptr)4581return nullptr;4582Result = make<NameWithTemplateArgs>(Result, TA);4583}4584break;4585}4586// ::= P <type> # pointer4587case 'P': {4588++First;4589Node *Ptr = getDerived().parseType();4590if (Ptr == nullptr)4591return nullptr;4592Result = make<PointerType>(Ptr);4593break;4594}4595// ::= R <type> # l-value reference4596case 'R': {4597++First;4598Node *Ref = getDerived().parseType();4599if (Ref == nullptr)4600return nullptr;4601Result = make<ReferenceType>(Ref, ReferenceKind::LValue);4602break;4603}4604// ::= O <type> # r-value reference (C++11)4605case 'O': {4606++First;4607Node *Ref = getDerived().parseType();4608if (Ref == nullptr)4609return nullptr;4610Result = make<ReferenceType>(Ref, ReferenceKind::RValue);4611break;4612}4613// ::= C <type> # complex pair (C99)4614case 'C': {4615++First;4616Node *P = getDerived().parseType();4617if (P == nullptr)4618return nullptr;4619Result = make<PostfixQualifiedType>(P, " complex");4620break;4621}4622// ::= G <type> # imaginary (C99)4623case 'G': {4624++First;4625Node *P = getDerived().parseType();4626if (P == nullptr)4627return P;4628Result = make<PostfixQualifiedType>(P, " imaginary");4629break;4630}4631// ::= <substitution> # See Compression below4632case 'S': {4633if (look(1) != 't') {4634bool IsSubst = false;4635Result = getDerived().parseUnscopedName(nullptr, &IsSubst);4636if (!Result)4637return nullptr;46384639// Sub could be either of:4640// <type> ::= <substitution>4641// <type> ::= <template-template-param> <template-args>4642//4643// <template-template-param> ::= <template-param>4644// ::= <substitution>4645//4646// If this is followed by some <template-args>, and we're permitted to4647// parse them, take the second production.46484649if (look() == 'I' && (!IsSubst || TryToParseTemplateArgs)) {4650if (!IsSubst)4651Subs.push_back(Result);4652Node *TA = getDerived().parseTemplateArgs();4653if (TA == nullptr)4654return nullptr;4655Result = make<NameWithTemplateArgs>(Result, TA);4656} else if (IsSubst) {4657// If all we parsed was a substitution, don't re-insert into the4658// substitution table.4659return Result;4660}4661break;4662}4663DEMANGLE_FALLTHROUGH;4664}4665// ::= <class-enum-type>4666default: {4667Result = getDerived().parseClassEnumType();4668break;4669}4670}46714672// If we parsed a type, insert it into the substitution table. Note that all4673// <builtin-type>s and <substitution>s have already bailed out, because they4674// don't get substitutions.4675if (Result != nullptr)4676Subs.push_back(Result);4677return Result;4678}46794680template <typename Derived, typename Alloc>4681Node *4682AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(std::string_view Kind,4683Node::Prec Prec) {4684Node *E = getDerived().parseExpr();4685if (E == nullptr)4686return nullptr;4687return make<PrefixExpr>(Kind, E, Prec);4688}46894690template <typename Derived, typename Alloc>4691Node *4692AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(std::string_view Kind,4693Node::Prec Prec) {4694Node *LHS = getDerived().parseExpr();4695if (LHS == nullptr)4696return nullptr;4697Node *RHS = getDerived().parseExpr();4698if (RHS == nullptr)4699return nullptr;4700return make<BinaryExpr>(LHS, Kind, RHS, Prec);4701}47024703template <typename Derived, typename Alloc>4704Node *AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(4705std::string_view Lit) {4706std::string_view Tmp = parseNumber(true);4707if (!Tmp.empty() && consumeIf('E'))4708return make<IntegerLiteral>(Lit, Tmp);4709return nullptr;4710}47114712// <CV-Qualifiers> ::= [r] [V] [K]4713template <typename Alloc, typename Derived>4714Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {4715Qualifiers CVR = QualNone;4716if (consumeIf('r'))4717CVR |= QualRestrict;4718if (consumeIf('V'))4719CVR |= QualVolatile;4720if (consumeIf('K'))4721CVR |= QualConst;4722return CVR;4723}47244725// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter4726// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters4727// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter4728// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters4729// ::= fpT # 'this' expression (not part of standard?)4730template <typename Derived, typename Alloc>4731Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {4732if (consumeIf("fpT"))4733return make<NameType>("this");4734if (consumeIf("fp")) {4735parseCVQualifiers();4736std::string_view Num = parseNumber();4737if (!consumeIf('_'))4738return nullptr;4739return make<FunctionParam>(Num);4740}4741if (consumeIf("fL")) {4742if (parseNumber().empty())4743return nullptr;4744if (!consumeIf('p'))4745return nullptr;4746parseCVQualifiers();4747std::string_view Num = parseNumber();4748if (!consumeIf('_'))4749return nullptr;4750return make<FunctionParam>(Num);4751}4752return nullptr;4753}47544755// cv <type> <expression> # conversion with one argument4756// cv <type> _ <expression>* E # conversion with a different number of arguments4757template <typename Derived, typename Alloc>4758Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {4759if (!consumeIf("cv"))4760return nullptr;4761Node *Ty;4762{4763ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);4764Ty = getDerived().parseType();4765}47664767if (Ty == nullptr)4768return nullptr;47694770if (consumeIf('_')) {4771size_t ExprsBegin = Names.size();4772while (!consumeIf('E')) {4773Node *E = getDerived().parseExpr();4774if (E == nullptr)4775return E;4776Names.push_back(E);4777}4778NodeArray Exprs = popTrailingNodeArray(ExprsBegin);4779return make<ConversionExpr>(Ty, Exprs);4780}47814782Node *E[1] = {getDerived().parseExpr()};4783if (E[0] == nullptr)4784return nullptr;4785return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));4786}47874788// <expr-primary> ::= L <type> <value number> E # integer literal4789// ::= L <type> <value float> E # floating literal4790// ::= L <string type> E # string literal4791// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")4792// ::= L <lambda type> E # lambda expression4793// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)4794// ::= L <mangled-name> E # external name4795template <typename Derived, typename Alloc>4796Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {4797if (!consumeIf('L'))4798return nullptr;4799switch (look()) {4800case 'w':4801++First;4802return getDerived().parseIntegerLiteral("wchar_t");4803case 'b':4804if (consumeIf("b0E"))4805return make<BoolExpr>(0);4806if (consumeIf("b1E"))4807return make<BoolExpr>(1);4808return nullptr;4809case 'c':4810++First;4811return getDerived().parseIntegerLiteral("char");4812case 'a':4813++First;4814return getDerived().parseIntegerLiteral("signed char");4815case 'h':4816++First;4817return getDerived().parseIntegerLiteral("unsigned char");4818case 's':4819++First;4820return getDerived().parseIntegerLiteral("short");4821case 't':4822++First;4823return getDerived().parseIntegerLiteral("unsigned short");4824case 'i':4825++First;4826return getDerived().parseIntegerLiteral("");4827case 'j':4828++First;4829return getDerived().parseIntegerLiteral("u");4830case 'l':4831++First;4832return getDerived().parseIntegerLiteral("l");4833case 'm':4834++First;4835return getDerived().parseIntegerLiteral("ul");4836case 'x':4837++First;4838return getDerived().parseIntegerLiteral("ll");4839case 'y':4840++First;4841return getDerived().parseIntegerLiteral("ull");4842case 'n':4843++First;4844return getDerived().parseIntegerLiteral("__int128");4845case 'o':4846++First;4847return getDerived().parseIntegerLiteral("unsigned __int128");4848case 'f':4849++First;4850return getDerived().template parseFloatingLiteral<float>();4851case 'd':4852++First;4853return getDerived().template parseFloatingLiteral<double>();4854case 'e':4855++First;4856#if defined(__powerpc__) || defined(__s390__)4857// Handle cases where long doubles encoded with e have the same size4858// and representation as doubles.4859return getDerived().template parseFloatingLiteral<double>();4860#else4861return getDerived().template parseFloatingLiteral<long double>();4862#endif4863case '_':4864if (consumeIf("_Z")) {4865Node *R = getDerived().parseEncoding();4866if (R != nullptr && consumeIf('E'))4867return R;4868}4869return nullptr;4870case 'A': {4871Node *T = getDerived().parseType();4872if (T == nullptr)4873return nullptr;4874// FIXME: We need to include the string contents in the mangling.4875if (consumeIf('E'))4876return make<StringLiteral>(T);4877return nullptr;4878}4879case 'D':4880if (consumeIf("Dn") && (consumeIf('0'), consumeIf('E')))4881return make<NameType>("nullptr");4882return nullptr;4883case 'T':4884// Invalid mangled name per4885// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html4886return nullptr;4887case 'U': {4888// FIXME: Should we support LUb... for block literals?4889if (look(1) != 'l')4890return nullptr;4891Node *T = parseUnnamedTypeName(nullptr);4892if (!T || !consumeIf('E'))4893return nullptr;4894return make<LambdaExpr>(T);4895}4896default: {4897// might be named type4898Node *T = getDerived().parseType();4899if (T == nullptr)4900return nullptr;4901std::string_view N = parseNumber(/*AllowNegative=*/true);4902if (N.empty())4903return nullptr;4904if (!consumeIf('E'))4905return nullptr;4906return make<EnumLiteral>(T, N);4907}4908}4909}49104911// <braced-expression> ::= <expression>4912// ::= di <field source-name> <braced-expression> # .name = expr4913// ::= dx <index expression> <braced-expression> # [expr] = expr4914// ::= dX <range begin expression> <range end expression> <braced-expression>4915template <typename Derived, typename Alloc>4916Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {4917if (look() == 'd') {4918switch (look(1)) {4919case 'i': {4920First += 2;4921Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);4922if (Field == nullptr)4923return nullptr;4924Node *Init = getDerived().parseBracedExpr();4925if (Init == nullptr)4926return nullptr;4927return make<BracedExpr>(Field, Init, /*isArray=*/false);4928}4929case 'x': {4930First += 2;4931Node *Index = getDerived().parseExpr();4932if (Index == nullptr)4933return nullptr;4934Node *Init = getDerived().parseBracedExpr();4935if (Init == nullptr)4936return nullptr;4937return make<BracedExpr>(Index, Init, /*isArray=*/true);4938}4939case 'X': {4940First += 2;4941Node *RangeBegin = getDerived().parseExpr();4942if (RangeBegin == nullptr)4943return nullptr;4944Node *RangeEnd = getDerived().parseExpr();4945if (RangeEnd == nullptr)4946return nullptr;4947Node *Init = getDerived().parseBracedExpr();4948if (Init == nullptr)4949return nullptr;4950return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);4951}4952}4953}4954return getDerived().parseExpr();4955}49564957// (not yet in the spec)4958// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>4959// ::= fR <binary-operator-name> <expression> <expression>4960// ::= fl <binary-operator-name> <expression>4961// ::= fr <binary-operator-name> <expression>4962template <typename Derived, typename Alloc>4963Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {4964if (!consumeIf('f'))4965return nullptr;49664967bool IsLeftFold = false, HasInitializer = false;4968switch (look()) {4969default:4970return nullptr;4971case 'L':4972IsLeftFold = true;4973HasInitializer = true;4974break;4975case 'R':4976HasInitializer = true;4977break;4978case 'l':4979IsLeftFold = true;4980break;4981case 'r':4982break;4983}4984++First;49854986const auto *Op = parseOperatorEncoding();4987if (!Op)4988return nullptr;4989if (!(Op->getKind() == OperatorInfo::Binary4990|| (Op->getKind() == OperatorInfo::Member4991&& Op->getName().back() == '*')))4992return nullptr;49934994Node *Pack = getDerived().parseExpr();4995if (Pack == nullptr)4996return nullptr;49974998Node *Init = nullptr;4999if (HasInitializer) {5000Init = getDerived().parseExpr();5001if (Init == nullptr)5002return nullptr;5003}50045005if (IsLeftFold && Init)5006std::swap(Pack, Init);50075008return make<FoldExpr>(IsLeftFold, Op->getSymbol(), Pack, Init);5009}50105011// <expression> ::= mc <parameter type> <expr> [<offset number>] E5012//5013// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/475014template <typename Derived, typename Alloc>5015Node *5016AbstractManglingParser<Derived, Alloc>::parsePointerToMemberConversionExpr(5017Node::Prec Prec) {5018Node *Ty = getDerived().parseType();5019if (!Ty)5020return nullptr;5021Node *Expr = getDerived().parseExpr();5022if (!Expr)5023return nullptr;5024std::string_view Offset = getDerived().parseNumber(true);5025if (!consumeIf('E'))5026return nullptr;5027return make<PointerToMemberConversionExpr>(Ty, Expr, Offset, Prec);5028}50295030// <expression> ::= so <referent type> <expr> [<offset number>] <union-selector>* [p] E5031// <union-selector> ::= _ [<number>]5032//5033// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/475034template <typename Derived, typename Alloc>5035Node *AbstractManglingParser<Derived, Alloc>::parseSubobjectExpr() {5036Node *Ty = getDerived().parseType();5037if (!Ty)5038return nullptr;5039Node *Expr = getDerived().parseExpr();5040if (!Expr)5041return nullptr;5042std::string_view Offset = getDerived().parseNumber(true);5043size_t SelectorsBegin = Names.size();5044while (consumeIf('_')) {5045Node *Selector = make<NameType>(parseNumber());5046if (!Selector)5047return nullptr;5048Names.push_back(Selector);5049}5050bool OnePastTheEnd = consumeIf('p');5051if (!consumeIf('E'))5052return nullptr;5053return make<SubobjectExpr>(5054Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd);5055}50565057template <typename Derived, typename Alloc>5058Node *AbstractManglingParser<Derived, Alloc>::parseConstraintExpr() {5059// Within this expression, all enclosing template parameter lists are in5060// scope.5061ScopedOverride<bool> SaveIncompleteTemplateParameterTracking(5062HasIncompleteTemplateParameterTracking, true);5063return getDerived().parseExpr();5064}50655066template <typename Derived, typename Alloc>5067Node *AbstractManglingParser<Derived, Alloc>::parseRequiresExpr() {5068NodeArray Params;5069if (consumeIf("rQ")) {5070// <expression> ::= rQ <bare-function-type> _ <requirement>+ E5071size_t ParamsBegin = Names.size();5072while (!consumeIf('_')) {5073Node *Type = getDerived().parseType();5074if (Type == nullptr)5075return nullptr;5076Names.push_back(Type);5077}5078Params = popTrailingNodeArray(ParamsBegin);5079} else if (!consumeIf("rq")) {5080// <expression> ::= rq <requirement>+ E5081return nullptr;5082}50835084size_t ReqsBegin = Names.size();5085do {5086Node *Constraint = nullptr;5087if (consumeIf('X')) {5088// <requirement> ::= X <expression> [N] [R <type-constraint>]5089Node *Expr = getDerived().parseExpr();5090if (Expr == nullptr)5091return nullptr;5092bool Noexcept = consumeIf('N');5093Node *TypeReq = nullptr;5094if (consumeIf('R')) {5095TypeReq = getDerived().parseName();5096if (TypeReq == nullptr)5097return nullptr;5098}5099Constraint = make<ExprRequirement>(Expr, Noexcept, TypeReq);5100} else if (consumeIf('T')) {5101// <requirement> ::= T <type>5102Node *Type = getDerived().parseType();5103if (Type == nullptr)5104return nullptr;5105Constraint = make<TypeRequirement>(Type);5106} else if (consumeIf('Q')) {5107// <requirement> ::= Q <constraint-expression>5108//5109// FIXME: We use <expression> instead of <constraint-expression>. Either5110// the requires expression is already inside a constraint expression, in5111// which case it makes no difference, or we're in a requires-expression5112// that might be partially-substituted, where the language behavior is5113// not yet settled and clang mangles after substitution.5114Node *NestedReq = getDerived().parseExpr();5115if (NestedReq == nullptr)5116return nullptr;5117Constraint = make<NestedRequirement>(NestedReq);5118}5119if (Constraint == nullptr)5120return nullptr;5121Names.push_back(Constraint);5122} while (!consumeIf('E'));51235124return make<RequiresExpr>(Params, popTrailingNodeArray(ReqsBegin));5125}51265127// <expression> ::= <unary operator-name> <expression>5128// ::= <binary operator-name> <expression> <expression>5129// ::= <ternary operator-name> <expression> <expression> <expression>5130// ::= cl <expression>+ E # call5131// ::= cp <base-unresolved-name> <expression>* E # (name) (expr-list), call that would use argument-dependent lookup but for the parentheses5132// ::= cv <type> <expression> # conversion with one argument5133// ::= cv <type> _ <expression>* E # conversion with a different number of arguments5134// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type5135// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)5136// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type5137// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)5138// ::= [gs] dl <expression> # delete expression5139// ::= [gs] da <expression> # delete[] expression5140// ::= pp_ <expression> # prefix ++5141// ::= mm_ <expression> # prefix --5142// ::= ti <type> # typeid (type)5143// ::= te <expression> # typeid (expression)5144// ::= dc <type> <expression> # dynamic_cast<type> (expression)5145// ::= sc <type> <expression> # static_cast<type> (expression)5146// ::= cc <type> <expression> # const_cast<type> (expression)5147// ::= rc <type> <expression> # reinterpret_cast<type> (expression)5148// ::= st <type> # sizeof (a type)5149// ::= sz <expression> # sizeof (an expression)5150// ::= at <type> # alignof (a type)5151// ::= az <expression> # alignof (an expression)5152// ::= nx <expression> # noexcept (expression)5153// ::= <template-param>5154// ::= <function-param>5155// ::= dt <expression> <unresolved-name> # expr.name5156// ::= pt <expression> <unresolved-name> # expr->name5157// ::= ds <expression> <expression> # expr.*expr5158// ::= sZ <template-param> # size of a parameter pack5159// ::= sZ <function-param> # size of a function parameter pack5160// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template5161// ::= sp <expression> # pack expansion5162// ::= tw <expression> # throw expression5163// ::= tr # throw with no operand (rethrow)5164// ::= <unresolved-name> # f(p), N::f(p), ::f(p),5165// # freestanding dependent name (e.g., T::x),5166// # objectless nonstatic member reference5167// ::= fL <binary-operator-name> <expression> <expression>5168// ::= fR <binary-operator-name> <expression> <expression>5169// ::= fl <binary-operator-name> <expression>5170// ::= fr <binary-operator-name> <expression>5171// ::= <expr-primary>5172template <typename Derived, typename Alloc>5173Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {5174bool Global = consumeIf("gs");51755176const auto *Op = parseOperatorEncoding();5177if (Op) {5178auto Sym = Op->getSymbol();5179switch (Op->getKind()) {5180case OperatorInfo::Binary:5181// Binary operator: lhs @ rhs5182return getDerived().parseBinaryExpr(Sym, Op->getPrecedence());5183case OperatorInfo::Prefix:5184// Prefix unary operator: @ expr5185return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());5186case OperatorInfo::Postfix: {5187// Postfix unary operator: expr @5188if (consumeIf('_'))5189return getDerived().parsePrefixExpr(Sym, Op->getPrecedence());5190Node *Ex = getDerived().parseExpr();5191if (Ex == nullptr)5192return nullptr;5193return make<PostfixExpr>(Ex, Sym, Op->getPrecedence());5194}5195case OperatorInfo::Array: {5196// Array Index: lhs [ rhs ]5197Node *Base = getDerived().parseExpr();5198if (Base == nullptr)5199return nullptr;5200Node *Index = getDerived().parseExpr();5201if (Index == nullptr)5202return nullptr;5203return make<ArraySubscriptExpr>(Base, Index, Op->getPrecedence());5204}5205case OperatorInfo::Member: {5206// Member access lhs @ rhs5207Node *LHS = getDerived().parseExpr();5208if (LHS == nullptr)5209return nullptr;5210Node *RHS = getDerived().parseExpr();5211if (RHS == nullptr)5212return nullptr;5213return make<MemberExpr>(LHS, Sym, RHS, Op->getPrecedence());5214}5215case OperatorInfo::New: {5216// New5217// # new (expr-list) type [(init)]5218// [gs] nw <expression>* _ <type> [pi <expression>*] E5219// # new[] (expr-list) type [(init)]5220// [gs] na <expression>* _ <type> [pi <expression>*] E5221size_t Exprs = Names.size();5222while (!consumeIf('_')) {5223Node *Ex = getDerived().parseExpr();5224if (Ex == nullptr)5225return nullptr;5226Names.push_back(Ex);5227}5228NodeArray ExprList = popTrailingNodeArray(Exprs);5229Node *Ty = getDerived().parseType();5230if (Ty == nullptr)5231return nullptr;5232bool HaveInits = consumeIf("pi");5233size_t InitsBegin = Names.size();5234while (!consumeIf('E')) {5235if (!HaveInits)5236return nullptr;5237Node *Init = getDerived().parseExpr();5238if (Init == nullptr)5239return Init;5240Names.push_back(Init);5241}5242NodeArray Inits = popTrailingNodeArray(InitsBegin);5243return make<NewExpr>(ExprList, Ty, Inits, Global,5244/*IsArray=*/Op->getFlag(), Op->getPrecedence());5245}5246case OperatorInfo::Del: {5247// Delete5248Node *Ex = getDerived().parseExpr();5249if (Ex == nullptr)5250return nullptr;5251return make<DeleteExpr>(Ex, Global, /*IsArray=*/Op->getFlag(),5252Op->getPrecedence());5253}5254case OperatorInfo::Call: {5255// Function Call5256Node *Callee = getDerived().parseExpr();5257if (Callee == nullptr)5258return nullptr;5259size_t ExprsBegin = Names.size();5260while (!consumeIf('E')) {5261Node *E = getDerived().parseExpr();5262if (E == nullptr)5263return nullptr;5264Names.push_back(E);5265}5266return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin),5267/*IsParen=*/Op->getFlag(), Op->getPrecedence());5268}5269case OperatorInfo::CCast: {5270// C Cast: (type)expr5271Node *Ty;5272{5273ScopedOverride<bool> SaveTemp(TryToParseTemplateArgs, false);5274Ty = getDerived().parseType();5275}5276if (Ty == nullptr)5277return nullptr;52785279size_t ExprsBegin = Names.size();5280bool IsMany = consumeIf('_');5281while (!consumeIf('E')) {5282Node *E = getDerived().parseExpr();5283if (E == nullptr)5284return E;5285Names.push_back(E);5286if (!IsMany)5287break;5288}5289NodeArray Exprs = popTrailingNodeArray(ExprsBegin);5290if (!IsMany && Exprs.size() != 1)5291return nullptr;5292return make<ConversionExpr>(Ty, Exprs, Op->getPrecedence());5293}5294case OperatorInfo::Conditional: {5295// Conditional operator: expr ? expr : expr5296Node *Cond = getDerived().parseExpr();5297if (Cond == nullptr)5298return nullptr;5299Node *LHS = getDerived().parseExpr();5300if (LHS == nullptr)5301return nullptr;5302Node *RHS = getDerived().parseExpr();5303if (RHS == nullptr)5304return nullptr;5305return make<ConditionalExpr>(Cond, LHS, RHS, Op->getPrecedence());5306}5307case OperatorInfo::NamedCast: {5308// Named cast operation, @<type>(expr)5309Node *Ty = getDerived().parseType();5310if (Ty == nullptr)5311return nullptr;5312Node *Ex = getDerived().parseExpr();5313if (Ex == nullptr)5314return nullptr;5315return make<CastExpr>(Sym, Ty, Ex, Op->getPrecedence());5316}5317case OperatorInfo::OfIdOp: {5318// [sizeof/alignof/typeid] ( <type>|<expr> )5319Node *Arg =5320Op->getFlag() ? getDerived().parseType() : getDerived().parseExpr();5321if (!Arg)5322return nullptr;5323return make<EnclosingExpr>(Sym, Arg, Op->getPrecedence());5324}5325case OperatorInfo::NameOnly: {5326// Not valid as an expression operand.5327return nullptr;5328}5329}5330DEMANGLE_UNREACHABLE;5331}53325333if (numLeft() < 2)5334return nullptr;53355336if (look() == 'L')5337return getDerived().parseExprPrimary();5338if (look() == 'T')5339return getDerived().parseTemplateParam();5340if (look() == 'f') {5341// Disambiguate a fold expression from a <function-param>.5342if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))5343return getDerived().parseFunctionParam();5344return getDerived().parseFoldExpr();5345}5346if (consumeIf("il")) {5347size_t InitsBegin = Names.size();5348while (!consumeIf('E')) {5349Node *E = getDerived().parseBracedExpr();5350if (E == nullptr)5351return nullptr;5352Names.push_back(E);5353}5354return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));5355}5356if (consumeIf("mc"))5357return parsePointerToMemberConversionExpr(Node::Prec::Unary);5358if (consumeIf("nx")) {5359Node *Ex = getDerived().parseExpr();5360if (Ex == nullptr)5361return Ex;5362return make<EnclosingExpr>("noexcept ", Ex, Node::Prec::Unary);5363}5364if (look() == 'r' && (look(1) == 'q' || look(1) == 'Q'))5365return parseRequiresExpr();5366if (consumeIf("so"))5367return parseSubobjectExpr();5368if (consumeIf("sp")) {5369Node *Child = getDerived().parseExpr();5370if (Child == nullptr)5371return nullptr;5372return make<ParameterPackExpansion>(Child);5373}5374if (consumeIf("sZ")) {5375if (look() == 'T') {5376Node *R = getDerived().parseTemplateParam();5377if (R == nullptr)5378return nullptr;5379return make<SizeofParamPackExpr>(R);5380}5381Node *FP = getDerived().parseFunctionParam();5382if (FP == nullptr)5383return nullptr;5384return make<EnclosingExpr>("sizeof... ", FP);5385}5386if (consumeIf("sP")) {5387size_t ArgsBegin = Names.size();5388while (!consumeIf('E')) {5389Node *Arg = getDerived().parseTemplateArg();5390if (Arg == nullptr)5391return nullptr;5392Names.push_back(Arg);5393}5394auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));5395if (!Pack)5396return nullptr;5397return make<EnclosingExpr>("sizeof... ", Pack);5398}5399if (consumeIf("tl")) {5400Node *Ty = getDerived().parseType();5401if (Ty == nullptr)5402return nullptr;5403size_t InitsBegin = Names.size();5404while (!consumeIf('E')) {5405Node *E = getDerived().parseBracedExpr();5406if (E == nullptr)5407return nullptr;5408Names.push_back(E);5409}5410return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));5411}5412if (consumeIf("tr"))5413return make<NameType>("throw");5414if (consumeIf("tw")) {5415Node *Ex = getDerived().parseExpr();5416if (Ex == nullptr)5417return nullptr;5418return make<ThrowExpr>(Ex);5419}5420if (consumeIf('u')) {5421Node *Name = getDerived().parseSourceName(/*NameState=*/nullptr);5422if (!Name)5423return nullptr;5424// Special case legacy __uuidof mangling. The 't' and 'z' appear where the5425// standard encoding expects a <template-arg>, and would be otherwise be5426// interpreted as <type> node 'short' or 'ellipsis'. However, neither5427// __uuidof(short) nor __uuidof(...) can actually appear, so there is no5428// actual conflict here.5429bool IsUUID = false;5430Node *UUID = nullptr;5431if (Name->getBaseName() == "__uuidof") {5432if (consumeIf('t')) {5433UUID = getDerived().parseType();5434IsUUID = true;5435} else if (consumeIf('z')) {5436UUID = getDerived().parseExpr();5437IsUUID = true;5438}5439}5440size_t ExprsBegin = Names.size();5441if (IsUUID) {5442if (UUID == nullptr)5443return nullptr;5444Names.push_back(UUID);5445} else {5446while (!consumeIf('E')) {5447Node *E = getDerived().parseTemplateArg();5448if (E == nullptr)5449return E;5450Names.push_back(E);5451}5452}5453return make<CallExpr>(Name, popTrailingNodeArray(ExprsBegin),5454/*IsParen=*/false, Node::Prec::Postfix);5455}54565457// Only unresolved names remain.5458return getDerived().parseUnresolvedName(Global);5459}54605461// <call-offset> ::= h <nv-offset> _5462// ::= v <v-offset> _5463//5464// <nv-offset> ::= <offset number>5465// # non-virtual base override5466//5467// <v-offset> ::= <offset number> _ <virtual offset number>5468// # virtual base override, with vcall offset5469template <typename Alloc, typename Derived>5470bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {5471// Just scan through the call offset, we never add this information into the5472// output.5473if (consumeIf('h'))5474return parseNumber(true).empty() || !consumeIf('_');5475if (consumeIf('v'))5476return parseNumber(true).empty() || !consumeIf('_') ||5477parseNumber(true).empty() || !consumeIf('_');5478return true;5479}54805481// <special-name> ::= TV <type> # virtual table5482// ::= TT <type> # VTT structure (construction vtable index)5483// ::= TI <type> # typeinfo structure5484// ::= TS <type> # typeinfo name (null-terminated byte string)5485// ::= Tc <call-offset> <call-offset> <base encoding>5486// # base is the nominal target function of thunk5487// # first call-offset is 'this' adjustment5488// # second call-offset is result adjustment5489// ::= T <call-offset> <base encoding>5490// # base is the nominal target function of thunk5491// # Guard variable for one-time initialization5492// ::= GV <object name>5493// # No <type>5494// ::= TW <object name> # Thread-local wrapper5495// ::= TH <object name> # Thread-local initialization5496// ::= GR <object name> _ # First temporary5497// ::= GR <object name> <seq-id> _ # Subsequent temporaries5498// # construction vtable for second-in-first5499// extension ::= TC <first type> <number> _ <second type>5500// extension ::= GR <object name> # reference temporary for object5501// extension ::= GI <module name> # module global initializer5502template <typename Derived, typename Alloc>5503Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {5504switch (look()) {5505case 'T':5506switch (look(1)) {5507// TA <template-arg> # template parameter object5508//5509// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/635510case 'A': {5511First += 2;5512Node *Arg = getDerived().parseTemplateArg();5513if (Arg == nullptr)5514return nullptr;5515return make<SpecialName>("template parameter object for ", Arg);5516}5517// TV <type> # virtual table5518case 'V': {5519First += 2;5520Node *Ty = getDerived().parseType();5521if (Ty == nullptr)5522return nullptr;5523return make<SpecialName>("vtable for ", Ty);5524}5525// TT <type> # VTT structure (construction vtable index)5526case 'T': {5527First += 2;5528Node *Ty = getDerived().parseType();5529if (Ty == nullptr)5530return nullptr;5531return make<SpecialName>("VTT for ", Ty);5532}5533// TI <type> # typeinfo structure5534case 'I': {5535First += 2;5536Node *Ty = getDerived().parseType();5537if (Ty == nullptr)5538return nullptr;5539return make<SpecialName>("typeinfo for ", Ty);5540}5541// TS <type> # typeinfo name (null-terminated byte string)5542case 'S': {5543First += 2;5544Node *Ty = getDerived().parseType();5545if (Ty == nullptr)5546return nullptr;5547return make<SpecialName>("typeinfo name for ", Ty);5548}5549// Tc <call-offset> <call-offset> <base encoding>5550case 'c': {5551First += 2;5552if (parseCallOffset() || parseCallOffset())5553return nullptr;5554Node *Encoding = getDerived().parseEncoding();5555if (Encoding == nullptr)5556return nullptr;5557return make<SpecialName>("covariant return thunk to ", Encoding);5558}5559// extension ::= TC <first type> <number> _ <second type>5560// # construction vtable for second-in-first5561case 'C': {5562First += 2;5563Node *FirstType = getDerived().parseType();5564if (FirstType == nullptr)5565return nullptr;5566if (parseNumber(true).empty() || !consumeIf('_'))5567return nullptr;5568Node *SecondType = getDerived().parseType();5569if (SecondType == nullptr)5570return nullptr;5571return make<CtorVtableSpecialName>(SecondType, FirstType);5572}5573// TW <object name> # Thread-local wrapper5574case 'W': {5575First += 2;5576Node *Name = getDerived().parseName();5577if (Name == nullptr)5578return nullptr;5579return make<SpecialName>("thread-local wrapper routine for ", Name);5580}5581// TH <object name> # Thread-local initialization5582case 'H': {5583First += 2;5584Node *Name = getDerived().parseName();5585if (Name == nullptr)5586return nullptr;5587return make<SpecialName>("thread-local initialization routine for ", Name);5588}5589// T <call-offset> <base encoding>5590default: {5591++First;5592bool IsVirt = look() == 'v';5593if (parseCallOffset())5594return nullptr;5595Node *BaseEncoding = getDerived().parseEncoding();5596if (BaseEncoding == nullptr)5597return nullptr;5598if (IsVirt)5599return make<SpecialName>("virtual thunk to ", BaseEncoding);5600else5601return make<SpecialName>("non-virtual thunk to ", BaseEncoding);5602}5603}5604case 'G':5605switch (look(1)) {5606// GV <object name> # Guard variable for one-time initialization5607case 'V': {5608First += 2;5609Node *Name = getDerived().parseName();5610if (Name == nullptr)5611return nullptr;5612return make<SpecialName>("guard variable for ", Name);5613}5614// GR <object name> # reference temporary for object5615// GR <object name> _ # First temporary5616// GR <object name> <seq-id> _ # Subsequent temporaries5617case 'R': {5618First += 2;5619Node *Name = getDerived().parseName();5620if (Name == nullptr)5621return nullptr;5622size_t Count;5623bool ParsedSeqId = !parseSeqId(&Count);5624if (!consumeIf('_') && ParsedSeqId)5625return nullptr;5626return make<SpecialName>("reference temporary for ", Name);5627}5628// GI <module-name> v5629case 'I': {5630First += 2;5631ModuleName *Module = nullptr;5632if (getDerived().parseModuleNameOpt(Module))5633return nullptr;5634if (Module == nullptr)5635return nullptr;5636return make<SpecialName>("initializer for module ", Module);5637}5638}5639}5640return nullptr;5641}56425643// <encoding> ::= <function name> <bare-function-type>5644// [`Q` <requires-clause expr>]5645// ::= <data name>5646// ::= <special-name>5647template <typename Derived, typename Alloc>5648Node *AbstractManglingParser<Derived, Alloc>::parseEncoding(bool ParseParams) {5649// The template parameters of an encoding are unrelated to those of the5650// enclosing context.5651SaveTemplateParams SaveTemplateParamsScope(this);56525653if (look() == 'G' || look() == 'T')5654return getDerived().parseSpecialName();56555656auto IsEndOfEncoding = [&] {5657// The set of chars that can potentially follow an <encoding> (none of which5658// can start a <type>). Enumerating these allows us to avoid speculative5659// parsing.5660return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';5661};56625663NameState NameInfo(this);5664Node *Name = getDerived().parseName(&NameInfo);5665if (Name == nullptr)5666return nullptr;56675668if (resolveForwardTemplateRefs(NameInfo))5669return nullptr;56705671if (IsEndOfEncoding())5672return Name;56735674// ParseParams may be false at the top level only, when called from parse().5675// For example in the mangled name _Z3fooILZ3BarEET_f, ParseParams may be5676// false when demangling 3fooILZ3BarEET_f but is always true when demangling5677// 3Bar.5678if (!ParseParams) {5679while (consume())5680;5681return Name;5682}56835684Node *Attrs = nullptr;5685if (consumeIf("Ua9enable_ifI")) {5686size_t BeforeArgs = Names.size();5687while (!consumeIf('E')) {5688Node *Arg = getDerived().parseTemplateArg();5689if (Arg == nullptr)5690return nullptr;5691Names.push_back(Arg);5692}5693Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));5694if (!Attrs)5695return nullptr;5696}56975698Node *ReturnType = nullptr;5699if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {5700ReturnType = getDerived().parseType();5701if (ReturnType == nullptr)5702return nullptr;5703}57045705NodeArray Params;5706if (!consumeIf('v')) {5707size_t ParamsBegin = Names.size();5708do {5709Node *Ty = getDerived().parseType();5710if (Ty == nullptr)5711return nullptr;57125713const bool IsFirstParam = ParamsBegin == Names.size();5714if (NameInfo.HasExplicitObjectParameter && IsFirstParam)5715Ty = make<ExplicitObjectParameter>(Ty);57165717if (Ty == nullptr)5718return nullptr;57195720Names.push_back(Ty);5721} while (!IsEndOfEncoding() && look() != 'Q');5722Params = popTrailingNodeArray(ParamsBegin);5723}57245725Node *Requires = nullptr;5726if (consumeIf('Q')) {5727Requires = getDerived().parseConstraintExpr();5728if (!Requires)5729return nullptr;5730}57315732return make<FunctionEncoding>(ReturnType, Name, Params, Attrs, Requires,5733NameInfo.CVQualifiers,5734NameInfo.ReferenceQualifier);5735}57365737template <class Float>5738struct FloatData;57395740template <>5741struct FloatData<float>5742{5743static const size_t mangled_size = 8;5744static const size_t max_demangled_size = 24;5745static constexpr const char* spec = "%af";5746};57475748template <>5749struct FloatData<double>5750{5751static const size_t mangled_size = 16;5752static const size_t max_demangled_size = 32;5753static constexpr const char* spec = "%a";5754};57555756template <>5757struct FloatData<long double>5758{5759#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 1065760static const size_t mangled_size = 32;5761#elif __LDBL_MANT_DIG__ == 53 || defined(_MSC_VER)5762// MSVC doesn't define __LDBL_MANT_DIG__, but it has long double equal to5763// regular double on all current architectures.5764static const size_t mangled_size = 16;5765#elif __LDBL_MANT_DIG__ == 645766static const size_t mangled_size = 20;5767#else5768#error Unknown size for __LDBL_MANT_DIG__5769#endif5770// `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes.5771// 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits.5772// Negatives are one character longer than positives.5773// `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the5774// same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128.5775static const size_t max_demangled_size = 42;5776static constexpr const char *spec = "%LaL";5777};57785779template <typename Alloc, typename Derived>5780template <class Float>5781Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {5782const size_t N = FloatData<Float>::mangled_size;5783if (numLeft() <= N)5784return nullptr;5785std::string_view Data(First, N);5786for (char C : Data)5787if (!(C >= '0' && C <= '9') && !(C >= 'a' && C <= 'f'))5788return nullptr;5789First += N;5790if (!consumeIf('E'))5791return nullptr;5792return make<FloatLiteralImpl<Float>>(Data);5793}57945795// <seq-id> ::= <0-9A-Z>+5796template <typename Alloc, typename Derived>5797bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {5798if (!(look() >= '0' && look() <= '9') &&5799!(look() >= 'A' && look() <= 'Z'))5800return true;58015802size_t Id = 0;5803while (true) {5804if (look() >= '0' && look() <= '9') {5805Id *= 36;5806Id += static_cast<size_t>(look() - '0');5807} else if (look() >= 'A' && look() <= 'Z') {5808Id *= 36;5809Id += static_cast<size_t>(look() - 'A') + 10;5810} else {5811*Out = Id;5812return false;5813}5814++First;5815}5816}58175818// <substitution> ::= S <seq-id> _5819// ::= S_5820// <substitution> ::= Sa # ::std::allocator5821// <substitution> ::= Sb # ::std::basic_string5822// <substitution> ::= Ss # ::std::basic_string < char,5823// ::std::char_traits<char>,5824// ::std::allocator<char> >5825// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >5826// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >5827// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >5828// The St case is handled specially in parseNestedName.5829template <typename Derived, typename Alloc>5830Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {5831if (!consumeIf('S'))5832return nullptr;58335834if (look() >= 'a' && look() <= 'z') {5835SpecialSubKind Kind;5836switch (look()) {5837case 'a':5838Kind = SpecialSubKind::allocator;5839break;5840case 'b':5841Kind = SpecialSubKind::basic_string;5842break;5843case 'd':5844Kind = SpecialSubKind::iostream;5845break;5846case 'i':5847Kind = SpecialSubKind::istream;5848break;5849case 'o':5850Kind = SpecialSubKind::ostream;5851break;5852case 's':5853Kind = SpecialSubKind::string;5854break;5855default:5856return nullptr;5857}5858++First;5859auto *SpecialSub = make<SpecialSubstitution>(Kind);5860if (!SpecialSub)5861return nullptr;58625863// Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>5864// has ABI tags, the tags are appended to the substitution; the result is a5865// substitutable component.5866Node *WithTags = getDerived().parseAbiTags(SpecialSub);5867if (WithTags != SpecialSub) {5868Subs.push_back(WithTags);5869SpecialSub = WithTags;5870}5871return SpecialSub;5872}58735874// ::= S_5875if (consumeIf('_')) {5876if (Subs.empty())5877return nullptr;5878return Subs[0];5879}58805881// ::= S <seq-id> _5882size_t Index = 0;5883if (parseSeqId(&Index))5884return nullptr;5885++Index;5886if (!consumeIf('_') || Index >= Subs.size())5887return nullptr;5888return Subs[Index];5889}58905891// <template-param> ::= T_ # first template parameter5892// ::= T <parameter-2 non-negative number> _5893// ::= TL <level-1> __5894// ::= TL <level-1> _ <parameter-2 non-negative number> _5895template <typename Derived, typename Alloc>5896Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {5897const char *Begin = First;5898if (!consumeIf('T'))5899return nullptr;59005901size_t Level = 0;5902if (consumeIf('L')) {5903if (parsePositiveInteger(&Level))5904return nullptr;5905++Level;5906if (!consumeIf('_'))5907return nullptr;5908}59095910size_t Index = 0;5911if (!consumeIf('_')) {5912if (parsePositiveInteger(&Index))5913return nullptr;5914++Index;5915if (!consumeIf('_'))5916return nullptr;5917}59185919// We don't track enclosing template parameter levels well enough to reliably5920// substitute them all within a <constraint-expression>, so print the5921// parameter numbering instead for now.5922// TODO: Track all enclosing template parameters and substitute them here.5923if (HasIncompleteTemplateParameterTracking) {5924return make<NameType>(std::string_view(Begin, First - 1 - Begin));5925}59265927// If we're in a context where this <template-param> refers to a5928// <template-arg> further ahead in the mangled name (currently just conversion5929// operator types), then we should only look it up in the right context.5930// This can only happen at the outermost level.5931if (PermitForwardTemplateReferences && Level == 0) {5932Node *ForwardRef = make<ForwardTemplateReference>(Index);5933if (!ForwardRef)5934return nullptr;5935DEMANGLE_ASSERT(ForwardRef->getKind() == Node::KForwardTemplateReference,5936"");5937ForwardTemplateRefs.push_back(5938static_cast<ForwardTemplateReference *>(ForwardRef));5939return ForwardRef;5940}59415942if (Level >= TemplateParams.size() || !TemplateParams[Level] ||5943Index >= TemplateParams[Level]->size()) {5944// Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter5945// list are mangled as the corresponding artificial template type parameter.5946if (ParsingLambdaParamsAtLevel == Level && Level <= TemplateParams.size()) {5947// This will be popped by the ScopedTemplateParamList in5948// parseUnnamedTypeName.5949if (Level == TemplateParams.size())5950TemplateParams.push_back(nullptr);5951return make<NameType>("auto");5952}59535954return nullptr;5955}59565957return (*TemplateParams[Level])[Index];5958}59595960// <template-param-decl> ::= Ty # type parameter5961// ::= Tk <concept name> [<template-args>] # constrained type parameter5962// ::= Tn <type> # non-type parameter5963// ::= Tt <template-param-decl>* E # template parameter5964// ::= Tp <template-param-decl> # parameter pack5965template <typename Derived, typename Alloc>5966Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParamDecl(5967TemplateParamList *Params) {5968auto InventTemplateParamName = [&](TemplateParamKind Kind) {5969unsigned Index = NumSyntheticTemplateParameters[(int)Kind]++;5970Node *N = make<SyntheticTemplateParamName>(Kind, Index);5971if (N && Params)5972Params->push_back(N);5973return N;5974};59755976if (consumeIf("Ty")) {5977Node *Name = InventTemplateParamName(TemplateParamKind::Type);5978if (!Name)5979return nullptr;5980return make<TypeTemplateParamDecl>(Name);5981}59825983if (consumeIf("Tk")) {5984// We don't track enclosing template parameter levels well enough to5985// reliably demangle template parameter substitutions, so print an arbitrary5986// string in place of a parameter for now.5987// TODO: Track all enclosing template parameters and demangle substitutions.5988ScopedOverride<bool> SaveIncompleteTemplateParameterTrackingExpr(5989HasIncompleteTemplateParameterTracking, true);5990Node *Constraint = getDerived().parseName();5991if (!Constraint)5992return nullptr;5993Node *Name = InventTemplateParamName(TemplateParamKind::Type);5994if (!Name)5995return nullptr;5996return make<ConstrainedTypeTemplateParamDecl>(Constraint, Name);5997}59985999if (consumeIf("Tn")) {6000Node *Name = InventTemplateParamName(TemplateParamKind::NonType);6001if (!Name)6002return nullptr;6003Node *Type = parseType();6004if (!Type)6005return nullptr;6006return make<NonTypeTemplateParamDecl>(Name, Type);6007}60086009if (consumeIf("Tt")) {6010Node *Name = InventTemplateParamName(TemplateParamKind::Template);6011if (!Name)6012return nullptr;6013size_t ParamsBegin = Names.size();6014ScopedTemplateParamList TemplateTemplateParamParams(this);6015Node *Requires = nullptr;6016while (!consumeIf('E')) {6017Node *P = parseTemplateParamDecl(TemplateTemplateParamParams.params());6018if (!P)6019return nullptr;6020Names.push_back(P);6021if (consumeIf('Q')) {6022Requires = getDerived().parseConstraintExpr();6023if (Requires == nullptr || !consumeIf('E'))6024return nullptr;6025break;6026}6027}6028NodeArray InnerParams = popTrailingNodeArray(ParamsBegin);6029return make<TemplateTemplateParamDecl>(Name, InnerParams, Requires);6030}60316032if (consumeIf("Tp")) {6033Node *P = parseTemplateParamDecl(Params);6034if (!P)6035return nullptr;6036return make<TemplateParamPackDecl>(P);6037}60386039return nullptr;6040}60416042// <template-arg> ::= <type> # type or template6043// ::= X <expression> E # expression6044// ::= <expr-primary> # simple expressions6045// ::= J <template-arg>* E # argument pack6046// ::= LZ <encoding> E # extension6047// ::= <template-param-decl> <template-arg>6048template <typename Derived, typename Alloc>6049Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {6050switch (look()) {6051case 'X': {6052++First;6053Node *Arg = getDerived().parseExpr();6054if (Arg == nullptr || !consumeIf('E'))6055return nullptr;6056return Arg;6057}6058case 'J': {6059++First;6060size_t ArgsBegin = Names.size();6061while (!consumeIf('E')) {6062Node *Arg = getDerived().parseTemplateArg();6063if (Arg == nullptr)6064return nullptr;6065Names.push_back(Arg);6066}6067NodeArray Args = popTrailingNodeArray(ArgsBegin);6068return make<TemplateArgumentPack>(Args);6069}6070case 'L': {6071// ::= LZ <encoding> E # extension6072if (look(1) == 'Z') {6073First += 2;6074Node *Arg = getDerived().parseEncoding();6075if (Arg == nullptr || !consumeIf('E'))6076return nullptr;6077return Arg;6078}6079// ::= <expr-primary> # simple expressions6080return getDerived().parseExprPrimary();6081}6082case 'T': {6083// Either <template-param> or a <template-param-decl> <template-arg>.6084if (!getDerived().isTemplateParamDecl())6085return getDerived().parseType();6086Node *Param = getDerived().parseTemplateParamDecl(nullptr);6087if (!Param)6088return nullptr;6089Node *Arg = getDerived().parseTemplateArg();6090if (!Arg)6091return nullptr;6092return make<TemplateParamQualifiedArg>(Param, Arg);6093}6094default:6095return getDerived().parseType();6096}6097}60986099// <template-args> ::= I <template-arg>* [Q <requires-clause expr>] E6100// extension, the abi says <template-arg>+6101template <typename Derived, typename Alloc>6102Node *6103AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {6104if (!consumeIf('I'))6105return nullptr;61066107// <template-params> refer to the innermost <template-args>. Clear out any6108// outer args that we may have inserted into TemplateParams.6109if (TagTemplates) {6110TemplateParams.clear();6111TemplateParams.push_back(&OuterTemplateParams);6112OuterTemplateParams.clear();6113}61146115size_t ArgsBegin = Names.size();6116Node *Requires = nullptr;6117while (!consumeIf('E')) {6118if (TagTemplates) {6119Node *Arg = getDerived().parseTemplateArg();6120if (Arg == nullptr)6121return nullptr;6122Names.push_back(Arg);6123Node *TableEntry = Arg;6124if (Arg->getKind() == Node::KTemplateParamQualifiedArg) {6125TableEntry =6126static_cast<TemplateParamQualifiedArg *>(TableEntry)->getArg();6127}6128if (Arg->getKind() == Node::KTemplateArgumentPack) {6129TableEntry = make<ParameterPack>(6130static_cast<TemplateArgumentPack*>(TableEntry)->getElements());6131if (!TableEntry)6132return nullptr;6133}6134OuterTemplateParams.push_back(TableEntry);6135} else {6136Node *Arg = getDerived().parseTemplateArg();6137if (Arg == nullptr)6138return nullptr;6139Names.push_back(Arg);6140}6141if (consumeIf('Q')) {6142Requires = getDerived().parseConstraintExpr();6143if (!Requires || !consumeIf('E'))6144return nullptr;6145break;6146}6147}6148return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin), Requires);6149}61506151// <mangled-name> ::= _Z <encoding>6152// ::= <type>6153// extension ::= ___Z <encoding> _block_invoke6154// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+6155// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+6156template <typename Derived, typename Alloc>6157Node *AbstractManglingParser<Derived, Alloc>::parse(bool ParseParams) {6158if (consumeIf("_Z") || consumeIf("__Z")) {6159Node *Encoding = getDerived().parseEncoding(ParseParams);6160if (Encoding == nullptr)6161return nullptr;6162if (look() == '.') {6163Encoding =6164make<DotSuffix>(Encoding, std::string_view(First, Last - First));6165First = Last;6166}6167if (numLeft() != 0)6168return nullptr;6169return Encoding;6170}61716172if (consumeIf("___Z") || consumeIf("____Z")) {6173Node *Encoding = getDerived().parseEncoding(ParseParams);6174if (Encoding == nullptr || !consumeIf("_block_invoke"))6175return nullptr;6176bool RequireNumber = consumeIf('_');6177if (parseNumber().empty() && RequireNumber)6178return nullptr;6179if (look() == '.')6180First = Last;6181if (numLeft() != 0)6182return nullptr;6183return make<SpecialName>("invocation function for block in ", Encoding);6184}61856186Node *Ty = getDerived().parseType();6187if (numLeft() != 0)6188return nullptr;6189return Ty;6190}61916192template <typename Alloc>6193struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {6194using AbstractManglingParser<ManglingParser<Alloc>,6195Alloc>::AbstractManglingParser;6196};61976198inline void OutputBuffer::printLeft(const Node &N) { N.printLeft(*this); }61996200inline void OutputBuffer::printRight(const Node &N) { N.printRight(*this); }62016202DEMANGLE_NAMESPACE_END62036204#if defined(__clang__)6205#pragma clang diagnostic pop6206#endif62076208#endif // DEMANGLE_ITANIUMDEMANGLE_H620962106211