Path: blob/master/libs/c++abi/src/demangle/ItaniumDemangle.h
12346 views
//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===//1//2// The LLVM Compiler Infrastructure3//4// This file is dual licensed under the MIT and the University of Illinois Open5// Source Licenses. See LICENSE.TXT for details.6//7//===----------------------------------------------------------------------===//8//9// WARNING: This file defines its contents within an anonymous namespace. It10// should not be included anywhere other than cxa_demangle.h.11//12//===----------------------------------------------------------------------===//1314#ifndef LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H15#define LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H1617// FIXME: (possibly) incomplete list of features that clang mangles that this18// file does not yet support:19// - C++ modules TS2021#include "Compiler.h"22#include "StringView.h"23#include "Utility.h"2425#include <cassert>26#include <cctype>27#include <cstdio>28#include <cstdlib>29#include <cstring>30#include <numeric>31#include <utility>3233#define FOR_EACH_NODE_KIND(X) \34X(NodeArrayNode) \35X(DotSuffix) \36X(VendorExtQualType) \37X(QualType) \38X(ConversionOperatorType) \39X(PostfixQualifiedType) \40X(ElaboratedTypeSpefType) \41X(NameType) \42X(AbiTagAttr) \43X(EnableIfAttr) \44X(ObjCProtoName) \45X(PointerType) \46X(ReferenceType) \47X(PointerToMemberType) \48X(ArrayType) \49X(FunctionType) \50X(NoexceptSpec) \51X(DynamicExceptionSpec) \52X(FunctionEncoding) \53X(LiteralOperator) \54X(SpecialName) \55X(CtorVtableSpecialName) \56X(QualifiedName) \57X(NestedName) \58X(LocalName) \59X(VectorType) \60X(PixelVectorType) \61X(ParameterPack) \62X(TemplateArgumentPack) \63X(ParameterPackExpansion) \64X(TemplateArgs) \65X(ForwardTemplateReference) \66X(NameWithTemplateArgs) \67X(GlobalQualifiedName) \68X(StdQualifiedName) \69X(ExpandedSpecialSubstitution) \70X(SpecialSubstitution) \71X(CtorDtorName) \72X(DtorName) \73X(UnnamedTypeName) \74X(ClosureTypeName) \75X(StructuredBindingName) \76X(BinaryExpr) \77X(ArraySubscriptExpr) \78X(PostfixExpr) \79X(ConditionalExpr) \80X(MemberExpr) \81X(EnclosingExpr) \82X(CastExpr) \83X(SizeofParamPackExpr) \84X(CallExpr) \85X(NewExpr) \86X(DeleteExpr) \87X(PrefixExpr) \88X(FunctionParam) \89X(ConversionExpr) \90X(InitListExpr) \91X(FoldExpr) \92X(ThrowExpr) \93X(BoolExpr) \94X(IntegerCastExpr) \95X(IntegerLiteral) \96X(FloatLiteral) \97X(DoubleLiteral) \98X(LongDoubleLiteral) \99X(BracedExpr) \100X(BracedRangeExpr)101102namespace {103namespace itanium_demangle {104// Base class of all AST nodes. The AST is built by the parser, then is105// traversed by the printLeft/Right functions to produce a demangled string.106class Node {107public:108enum Kind : unsigned char {109#define ENUMERATOR(NodeKind) K ## NodeKind,110FOR_EACH_NODE_KIND(ENUMERATOR)111#undef ENUMERATOR112};113114/// Three-way bool to track a cached value. Unknown is possible if this node115/// has an unexpanded parameter pack below it that may affect this cache.116enum class Cache : unsigned char { Yes, No, Unknown, };117118private:119Kind K;120121// FIXME: Make these protected.122public:123/// Tracks if this node has a component on its right side, in which case we124/// need to call printRight.125Cache RHSComponentCache;126127/// Track if this node is a (possibly qualified) array type. This can affect128/// how we format the output string.129Cache ArrayCache;130131/// Track if this node is a (possibly qualified) function type. This can132/// affect how we format the output string.133Cache FunctionCache;134135public:136Node(Kind K_, Cache RHSComponentCache_ = Cache::No,137Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No)138: K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_),139FunctionCache(FunctionCache_) {}140141/// Visit the most-derived object corresponding to this object.142template<typename Fn> void visit(Fn F) const;143144// The following function is provided by all derived classes:145//146// Call F with arguments that, when passed to the constructor of this node,147// would construct an equivalent node.148//template<typename Fn> void match(Fn F) const;149150bool hasRHSComponent(OutputStream &S) const {151if (RHSComponentCache != Cache::Unknown)152return RHSComponentCache == Cache::Yes;153return hasRHSComponentSlow(S);154}155156bool hasArray(OutputStream &S) const {157if (ArrayCache != Cache::Unknown)158return ArrayCache == Cache::Yes;159return hasArraySlow(S);160}161162bool hasFunction(OutputStream &S) const {163if (FunctionCache != Cache::Unknown)164return FunctionCache == Cache::Yes;165return hasFunctionSlow(S);166}167168Kind getKind() const { return K; }169170virtual bool hasRHSComponentSlow(OutputStream &) const { return false; }171virtual bool hasArraySlow(OutputStream &) const { return false; }172virtual bool hasFunctionSlow(OutputStream &) const { return false; }173174// Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to175// get at a node that actually represents some concrete syntax.176virtual const Node *getSyntaxNode(OutputStream &) const {177return this;178}179180void print(OutputStream &S) const {181printLeft(S);182if (RHSComponentCache != Cache::No)183printRight(S);184}185186// Print the "left" side of this Node into OutputStream.187virtual void printLeft(OutputStream &) const = 0;188189// Print the "right". This distinction is necessary to represent C++ types190// that appear on the RHS of their subtype, such as arrays or functions.191// Since most types don't have such a component, provide a default192// implementation.193virtual void printRight(OutputStream &) const {}194195virtual StringView getBaseName() const { return StringView(); }196197// Silence compiler warnings, this dtor will never be called.198virtual ~Node() = default;199200#ifndef NDEBUG201DUMP_METHOD void dump() const;202#endif203};204205class NodeArray {206Node **Elements;207size_t NumElements;208209public:210NodeArray() : Elements(nullptr), NumElements(0) {}211NodeArray(Node **Elements_, size_t NumElements_)212: Elements(Elements_), NumElements(NumElements_) {}213214bool empty() const { return NumElements == 0; }215size_t size() const { return NumElements; }216217Node **begin() const { return Elements; }218Node **end() const { return Elements + NumElements; }219220Node *operator[](size_t Idx) const { return Elements[Idx]; }221222void printWithComma(OutputStream &S) const {223bool FirstElement = true;224for (size_t Idx = 0; Idx != NumElements; ++Idx) {225size_t BeforeComma = S.getCurrentPosition();226if (!FirstElement)227S += ", ";228size_t AfterComma = S.getCurrentPosition();229Elements[Idx]->print(S);230231// Elements[Idx] is an empty parameter pack expansion, we should erase the232// comma we just printed.233if (AfterComma == S.getCurrentPosition()) {234S.setCurrentPosition(BeforeComma);235continue;236}237238FirstElement = false;239}240}241};242243struct NodeArrayNode : Node {244NodeArray Array;245NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {}246247template<typename Fn> void match(Fn F) const { F(Array); }248249void printLeft(OutputStream &S) const override {250Array.printWithComma(S);251}252};253254class DotSuffix final : public Node {255const Node *Prefix;256const StringView Suffix;257258public:259DotSuffix(const Node *Prefix_, StringView Suffix_)260: Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {}261262template<typename Fn> void match(Fn F) const { F(Prefix, Suffix); }263264void printLeft(OutputStream &s) const override {265Prefix->print(s);266s += " (";267s += Suffix;268s += ")";269}270};271272class VendorExtQualType final : public Node {273const Node *Ty;274StringView Ext;275276public:277VendorExtQualType(const Node *Ty_, StringView Ext_)278: Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {}279280template<typename Fn> void match(Fn F) const { F(Ty, Ext); }281282void printLeft(OutputStream &S) const override {283Ty->print(S);284S += " ";285S += Ext;286}287};288289enum FunctionRefQual : unsigned char {290FrefQualNone,291FrefQualLValue,292FrefQualRValue,293};294295enum Qualifiers {296QualNone = 0,297QualConst = 0x1,298QualVolatile = 0x2,299QualRestrict = 0x4,300};301302inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) {303return Q1 = static_cast<Qualifiers>(Q1 | Q2);304}305306class QualType : public Node {307protected:308const Qualifiers Quals;309const Node *Child;310311void printQuals(OutputStream &S) const {312if (Quals & QualConst)313S += " const";314if (Quals & QualVolatile)315S += " volatile";316if (Quals & QualRestrict)317S += " restrict";318}319320public:321QualType(const Node *Child_, Qualifiers Quals_)322: Node(KQualType, Child_->RHSComponentCache,323Child_->ArrayCache, Child_->FunctionCache),324Quals(Quals_), Child(Child_) {}325326template<typename Fn> void match(Fn F) const { F(Child, Quals); }327328bool hasRHSComponentSlow(OutputStream &S) const override {329return Child->hasRHSComponent(S);330}331bool hasArraySlow(OutputStream &S) const override {332return Child->hasArray(S);333}334bool hasFunctionSlow(OutputStream &S) const override {335return Child->hasFunction(S);336}337338void printLeft(OutputStream &S) const override {339Child->printLeft(S);340printQuals(S);341}342343void printRight(OutputStream &S) const override { Child->printRight(S); }344};345346class ConversionOperatorType final : public Node {347const Node *Ty;348349public:350ConversionOperatorType(const Node *Ty_)351: Node(KConversionOperatorType), Ty(Ty_) {}352353template<typename Fn> void match(Fn F) const { F(Ty); }354355void printLeft(OutputStream &S) const override {356S += "operator ";357Ty->print(S);358}359};360361class PostfixQualifiedType final : public Node {362const Node *Ty;363const StringView Postfix;364365public:366PostfixQualifiedType(Node *Ty_, StringView Postfix_)367: Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {}368369template<typename Fn> void match(Fn F) const { F(Ty, Postfix); }370371void printLeft(OutputStream &s) const override {372Ty->printLeft(s);373s += Postfix;374}375};376377class NameType final : public Node {378const StringView Name;379380public:381NameType(StringView Name_) : Node(KNameType), Name(Name_) {}382383template<typename Fn> void match(Fn F) const { F(Name); }384385StringView getName() const { return Name; }386StringView getBaseName() const override { return Name; }387388void printLeft(OutputStream &s) const override { s += Name; }389};390391class ElaboratedTypeSpefType : public Node {392StringView Kind;393Node *Child;394public:395ElaboratedTypeSpefType(StringView Kind_, Node *Child_)396: Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {}397398template<typename Fn> void match(Fn F) const { F(Kind, Child); }399400void printLeft(OutputStream &S) const override {401S += Kind;402S += ' ';403Child->print(S);404}405};406407struct AbiTagAttr : Node {408Node *Base;409StringView Tag;410411AbiTagAttr(Node* Base_, StringView Tag_)412: Node(KAbiTagAttr, Base_->RHSComponentCache,413Base_->ArrayCache, Base_->FunctionCache),414Base(Base_), Tag(Tag_) {}415416template<typename Fn> void match(Fn F) const { F(Base, Tag); }417418void printLeft(OutputStream &S) const override {419Base->printLeft(S);420S += "[abi:";421S += Tag;422S += "]";423}424};425426class EnableIfAttr : public Node {427NodeArray Conditions;428public:429EnableIfAttr(NodeArray Conditions_)430: Node(KEnableIfAttr), Conditions(Conditions_) {}431432template<typename Fn> void match(Fn F) const { F(Conditions); }433434void printLeft(OutputStream &S) const override {435S += " [enable_if:";436Conditions.printWithComma(S);437S += ']';438}439};440441class ObjCProtoName : public Node {442const Node *Ty;443StringView Protocol;444445friend class PointerType;446447public:448ObjCProtoName(const Node *Ty_, StringView Protocol_)449: Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {}450451template<typename Fn> void match(Fn F) const { F(Ty, Protocol); }452453bool isObjCObject() const {454return Ty->getKind() == KNameType &&455static_cast<const NameType *>(Ty)->getName() == "objc_object";456}457458void printLeft(OutputStream &S) const override {459Ty->print(S);460S += "<";461S += Protocol;462S += ">";463}464};465466class PointerType final : public Node {467const Node *Pointee;468469public:470PointerType(const Node *Pointee_)471: Node(KPointerType, Pointee_->RHSComponentCache),472Pointee(Pointee_) {}473474template<typename Fn> void match(Fn F) const { F(Pointee); }475476bool hasRHSComponentSlow(OutputStream &S) const override {477return Pointee->hasRHSComponent(S);478}479480void printLeft(OutputStream &s) const override {481// We rewrite objc_object<SomeProtocol>* into id<SomeProtocol>.482if (Pointee->getKind() != KObjCProtoName ||483!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {484Pointee->printLeft(s);485if (Pointee->hasArray(s))486s += " ";487if (Pointee->hasArray(s) || Pointee->hasFunction(s))488s += "(";489s += "*";490} else {491const auto *objcProto = static_cast<const ObjCProtoName *>(Pointee);492s += "id<";493s += objcProto->Protocol;494s += ">";495}496}497498void printRight(OutputStream &s) const override {499if (Pointee->getKind() != KObjCProtoName ||500!static_cast<const ObjCProtoName *>(Pointee)->isObjCObject()) {501if (Pointee->hasArray(s) || Pointee->hasFunction(s))502s += ")";503Pointee->printRight(s);504}505}506};507508enum class ReferenceKind {509LValue,510RValue,511};512513// Represents either a LValue or an RValue reference type.514class ReferenceType : public Node {515const Node *Pointee;516ReferenceKind RK;517518mutable bool Printing = false;519520// Dig through any refs to refs, collapsing the ReferenceTypes as we go. The521// rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any522// other combination collapses to a lvalue ref.523std::pair<ReferenceKind, const Node *> collapse(OutputStream &S) const {524auto SoFar = std::make_pair(RK, Pointee);525for (;;) {526const Node *SN = SoFar.second->getSyntaxNode(S);527if (SN->getKind() != KReferenceType)528break;529auto *RT = static_cast<const ReferenceType *>(SN);530SoFar.second = RT->Pointee;531SoFar.first = std::min(SoFar.first, RT->RK);532}533return SoFar;534}535536public:537ReferenceType(const Node *Pointee_, ReferenceKind RK_)538: Node(KReferenceType, Pointee_->RHSComponentCache),539Pointee(Pointee_), RK(RK_) {}540541template<typename Fn> void match(Fn F) const { F(Pointee, RK); }542543bool hasRHSComponentSlow(OutputStream &S) const override {544return Pointee->hasRHSComponent(S);545}546547void printLeft(OutputStream &s) const override {548if (Printing)549return;550SwapAndRestore<bool> SavePrinting(Printing, true);551std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);552Collapsed.second->printLeft(s);553if (Collapsed.second->hasArray(s))554s += " ";555if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))556s += "(";557558s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&");559}560void printRight(OutputStream &s) const override {561if (Printing)562return;563SwapAndRestore<bool> SavePrinting(Printing, true);564std::pair<ReferenceKind, const Node *> Collapsed = collapse(s);565if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s))566s += ")";567Collapsed.second->printRight(s);568}569};570571class PointerToMemberType final : public Node {572const Node *ClassType;573const Node *MemberType;574575public:576PointerToMemberType(const Node *ClassType_, const Node *MemberType_)577: Node(KPointerToMemberType, MemberType_->RHSComponentCache),578ClassType(ClassType_), MemberType(MemberType_) {}579580template<typename Fn> void match(Fn F) const { F(ClassType, MemberType); }581582bool hasRHSComponentSlow(OutputStream &S) const override {583return MemberType->hasRHSComponent(S);584}585586void printLeft(OutputStream &s) const override {587MemberType->printLeft(s);588if (MemberType->hasArray(s) || MemberType->hasFunction(s))589s += "(";590else591s += " ";592ClassType->print(s);593s += "::*";594}595596void printRight(OutputStream &s) const override {597if (MemberType->hasArray(s) || MemberType->hasFunction(s))598s += ")";599MemberType->printRight(s);600}601};602603class NodeOrString {604const void *First;605const void *Second;606607public:608/* implicit */ NodeOrString(StringView Str) {609const char *FirstChar = Str.begin();610const char *SecondChar = Str.end();611if (SecondChar == nullptr) {612assert(FirstChar == SecondChar);613++FirstChar, ++SecondChar;614}615First = static_cast<const void *>(FirstChar);616Second = static_cast<const void *>(SecondChar);617}618619/* implicit */ NodeOrString(Node *N)620: First(static_cast<const void *>(N)), Second(nullptr) {}621NodeOrString() : First(nullptr), Second(nullptr) {}622623bool isString() const { return Second && First; }624bool isNode() const { return First && !Second; }625bool isEmpty() const { return !First && !Second; }626627StringView asString() const {628assert(isString());629return StringView(static_cast<const char *>(First),630static_cast<const char *>(Second));631}632633const Node *asNode() const {634assert(isNode());635return static_cast<const Node *>(First);636}637};638639class ArrayType final : public Node {640const Node *Base;641NodeOrString Dimension;642643public:644ArrayType(const Node *Base_, NodeOrString Dimension_)645: Node(KArrayType,646/*RHSComponentCache=*/Cache::Yes,647/*ArrayCache=*/Cache::Yes),648Base(Base_), Dimension(Dimension_) {}649650template<typename Fn> void match(Fn F) const { F(Base, Dimension); }651652bool hasRHSComponentSlow(OutputStream &) const override { return true; }653bool hasArraySlow(OutputStream &) const override { return true; }654655void printLeft(OutputStream &S) const override { Base->printLeft(S); }656657void printRight(OutputStream &S) const override {658if (S.back() != ']')659S += " ";660S += "[";661if (Dimension.isString())662S += Dimension.asString();663else if (Dimension.isNode())664Dimension.asNode()->print(S);665S += "]";666Base->printRight(S);667}668};669670class FunctionType final : public Node {671const Node *Ret;672NodeArray Params;673Qualifiers CVQuals;674FunctionRefQual RefQual;675const Node *ExceptionSpec;676677public:678FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_,679FunctionRefQual RefQual_, const Node *ExceptionSpec_)680: Node(KFunctionType,681/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,682/*FunctionCache=*/Cache::Yes),683Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_),684ExceptionSpec(ExceptionSpec_) {}685686template<typename Fn> void match(Fn F) const {687F(Ret, Params, CVQuals, RefQual, ExceptionSpec);688}689690bool hasRHSComponentSlow(OutputStream &) const override { return true; }691bool hasFunctionSlow(OutputStream &) const override { return true; }692693// Handle C++'s ... quirky decl grammar by using the left & right694// distinction. Consider:695// int (*f(float))(char) {}696// f is a function that takes a float and returns a pointer to a function697// that takes a char and returns an int. If we're trying to print f, start698// by printing out the return types's left, then print our parameters, then699// finally print right of the return type.700void printLeft(OutputStream &S) const override {701Ret->printLeft(S);702S += " ";703}704705void printRight(OutputStream &S) const override {706S += "(";707Params.printWithComma(S);708S += ")";709Ret->printRight(S);710711if (CVQuals & QualConst)712S += " const";713if (CVQuals & QualVolatile)714S += " volatile";715if (CVQuals & QualRestrict)716S += " restrict";717718if (RefQual == FrefQualLValue)719S += " &";720else if (RefQual == FrefQualRValue)721S += " &&";722723if (ExceptionSpec != nullptr) {724S += ' ';725ExceptionSpec->print(S);726}727}728};729730class NoexceptSpec : public Node {731const Node *E;732public:733NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {}734735template<typename Fn> void match(Fn F) const { F(E); }736737void printLeft(OutputStream &S) const override {738S += "noexcept(";739E->print(S);740S += ")";741}742};743744class DynamicExceptionSpec : public Node {745NodeArray Types;746public:747DynamicExceptionSpec(NodeArray Types_)748: Node(KDynamicExceptionSpec), Types(Types_) {}749750template<typename Fn> void match(Fn F) const { F(Types); }751752void printLeft(OutputStream &S) const override {753S += "throw(";754Types.printWithComma(S);755S += ')';756}757};758759class FunctionEncoding final : public Node {760const Node *Ret;761const Node *Name;762NodeArray Params;763const Node *Attrs;764Qualifiers CVQuals;765FunctionRefQual RefQual;766767public:768FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_,769const Node *Attrs_, Qualifiers CVQuals_,770FunctionRefQual RefQual_)771: Node(KFunctionEncoding,772/*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No,773/*FunctionCache=*/Cache::Yes),774Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_),775CVQuals(CVQuals_), RefQual(RefQual_) {}776777template<typename Fn> void match(Fn F) const {778F(Ret, Name, Params, Attrs, CVQuals, RefQual);779}780781Qualifiers getCVQuals() const { return CVQuals; }782FunctionRefQual getRefQual() const { return RefQual; }783NodeArray getParams() const { return Params; }784const Node *getReturnType() const { return Ret; }785786bool hasRHSComponentSlow(OutputStream &) const override { return true; }787bool hasFunctionSlow(OutputStream &) const override { return true; }788789const Node *getName() const { return Name; }790791void printLeft(OutputStream &S) const override {792if (Ret) {793Ret->printLeft(S);794if (!Ret->hasRHSComponent(S))795S += " ";796}797Name->print(S);798}799800void printRight(OutputStream &S) const override {801S += "(";802Params.printWithComma(S);803S += ")";804if (Ret)805Ret->printRight(S);806807if (CVQuals & QualConst)808S += " const";809if (CVQuals & QualVolatile)810S += " volatile";811if (CVQuals & QualRestrict)812S += " restrict";813814if (RefQual == FrefQualLValue)815S += " &";816else if (RefQual == FrefQualRValue)817S += " &&";818819if (Attrs != nullptr)820Attrs->print(S);821}822};823824class LiteralOperator : public Node {825const Node *OpName;826827public:828LiteralOperator(const Node *OpName_)829: Node(KLiteralOperator), OpName(OpName_) {}830831template<typename Fn> void match(Fn F) const { F(OpName); }832833void printLeft(OutputStream &S) const override {834S += "operator\"\" ";835OpName->print(S);836}837};838839class SpecialName final : public Node {840const StringView Special;841const Node *Child;842843public:844SpecialName(StringView Special_, const Node *Child_)845: Node(KSpecialName), Special(Special_), Child(Child_) {}846847template<typename Fn> void match(Fn F) const { F(Special, Child); }848849void printLeft(OutputStream &S) const override {850S += Special;851Child->print(S);852}853};854855class CtorVtableSpecialName final : public Node {856const Node *FirstType;857const Node *SecondType;858859public:860CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_)861: Node(KCtorVtableSpecialName),862FirstType(FirstType_), SecondType(SecondType_) {}863864template<typename Fn> void match(Fn F) const { F(FirstType, SecondType); }865866void printLeft(OutputStream &S) const override {867S += "construction vtable for ";868FirstType->print(S);869S += "-in-";870SecondType->print(S);871}872};873874struct NestedName : Node {875Node *Qual;876Node *Name;877878NestedName(Node *Qual_, Node *Name_)879: Node(KNestedName), Qual(Qual_), Name(Name_) {}880881template<typename Fn> void match(Fn F) const { F(Qual, Name); }882883StringView getBaseName() const override { return Name->getBaseName(); }884885void printLeft(OutputStream &S) const override {886Qual->print(S);887S += "::";888Name->print(S);889}890};891892struct LocalName : Node {893Node *Encoding;894Node *Entity;895896LocalName(Node *Encoding_, Node *Entity_)897: Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {}898899template<typename Fn> void match(Fn F) const { F(Encoding, Entity); }900901void printLeft(OutputStream &S) const override {902Encoding->print(S);903S += "::";904Entity->print(S);905}906};907908class QualifiedName final : public Node {909// qualifier::name910const Node *Qualifier;911const Node *Name;912913public:914QualifiedName(const Node *Qualifier_, const Node *Name_)915: Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {}916917template<typename Fn> void match(Fn F) const { F(Qualifier, Name); }918919StringView getBaseName() const override { return Name->getBaseName(); }920921void printLeft(OutputStream &S) const override {922Qualifier->print(S);923S += "::";924Name->print(S);925}926};927928class VectorType final : public Node {929const Node *BaseType;930const NodeOrString Dimension;931932public:933VectorType(const Node *BaseType_, NodeOrString Dimension_)934: Node(KVectorType), BaseType(BaseType_),935Dimension(Dimension_) {}936937template<typename Fn> void match(Fn F) const { F(BaseType, Dimension); }938939void printLeft(OutputStream &S) const override {940BaseType->print(S);941S += " vector[";942if (Dimension.isNode())943Dimension.asNode()->print(S);944else if (Dimension.isString())945S += Dimension.asString();946S += "]";947}948};949950class PixelVectorType final : public Node {951const NodeOrString Dimension;952953public:954PixelVectorType(NodeOrString Dimension_)955: Node(KPixelVectorType), Dimension(Dimension_) {}956957template<typename Fn> void match(Fn F) const { F(Dimension); }958959void printLeft(OutputStream &S) const override {960// FIXME: This should demangle as "vector pixel".961S += "pixel vector[";962S += Dimension.asString();963S += "]";964}965};966967/// An unexpanded parameter pack (either in the expression or type context). If968/// this AST is correct, this node will have a ParameterPackExpansion node above969/// it.970///971/// This node is created when some <template-args> are found that apply to an972/// <encoding>, and is stored in the TemplateParams table. In order for this to973/// appear in the final AST, it has to referenced via a <template-param> (ie,974/// T_).975class ParameterPack final : public Node {976NodeArray Data;977978// Setup OutputStream for a pack expansion unless we're already expanding one.979void initializePackExpansion(OutputStream &S) const {980if (S.CurrentPackMax == std::numeric_limits<unsigned>::max()) {981S.CurrentPackMax = static_cast<unsigned>(Data.size());982S.CurrentPackIndex = 0;983}984}985986public:987ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) {988ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown;989if (std::all_of(Data.begin(), Data.end(), [](Node* P) {990return P->ArrayCache == Cache::No;991}))992ArrayCache = Cache::No;993if (std::all_of(Data.begin(), Data.end(), [](Node* P) {994return P->FunctionCache == Cache::No;995}))996FunctionCache = Cache::No;997if (std::all_of(Data.begin(), Data.end(), [](Node* P) {998return P->RHSComponentCache == Cache::No;999}))1000RHSComponentCache = Cache::No;1001}10021003template<typename Fn> void match(Fn F) const { F(Data); }10041005bool hasRHSComponentSlow(OutputStream &S) const override {1006initializePackExpansion(S);1007size_t Idx = S.CurrentPackIndex;1008return Idx < Data.size() && Data[Idx]->hasRHSComponent(S);1009}1010bool hasArraySlow(OutputStream &S) const override {1011initializePackExpansion(S);1012size_t Idx = S.CurrentPackIndex;1013return Idx < Data.size() && Data[Idx]->hasArray(S);1014}1015bool hasFunctionSlow(OutputStream &S) const override {1016initializePackExpansion(S);1017size_t Idx = S.CurrentPackIndex;1018return Idx < Data.size() && Data[Idx]->hasFunction(S);1019}1020const Node *getSyntaxNode(OutputStream &S) const override {1021initializePackExpansion(S);1022size_t Idx = S.CurrentPackIndex;1023return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this;1024}10251026void printLeft(OutputStream &S) const override {1027initializePackExpansion(S);1028size_t Idx = S.CurrentPackIndex;1029if (Idx < Data.size())1030Data[Idx]->printLeft(S);1031}1032void printRight(OutputStream &S) const override {1033initializePackExpansion(S);1034size_t Idx = S.CurrentPackIndex;1035if (Idx < Data.size())1036Data[Idx]->printRight(S);1037}1038};10391040/// A variadic template argument. This node represents an occurrence of1041/// J<something>E in some <template-args>. It isn't itself unexpanded, unless1042/// one of it's Elements is. The parser inserts a ParameterPack into the1043/// TemplateParams table if the <template-args> this pack belongs to apply to an1044/// <encoding>.1045class TemplateArgumentPack final : public Node {1046NodeArray Elements;1047public:1048TemplateArgumentPack(NodeArray Elements_)1049: Node(KTemplateArgumentPack), Elements(Elements_) {}10501051template<typename Fn> void match(Fn F) const { F(Elements); }10521053NodeArray getElements() const { return Elements; }10541055void printLeft(OutputStream &S) const override {1056Elements.printWithComma(S);1057}1058};10591060/// A pack expansion. Below this node, there are some unexpanded ParameterPacks1061/// which each have Child->ParameterPackSize elements.1062class ParameterPackExpansion final : public Node {1063const Node *Child;10641065public:1066ParameterPackExpansion(const Node *Child_)1067: Node(KParameterPackExpansion), Child(Child_) {}10681069template<typename Fn> void match(Fn F) const { F(Child); }10701071const Node *getChild() const { return Child; }10721073void printLeft(OutputStream &S) const override {1074constexpr unsigned Max = std::numeric_limits<unsigned>::max();1075SwapAndRestore<unsigned> SavePackIdx(S.CurrentPackIndex, Max);1076SwapAndRestore<unsigned> SavePackMax(S.CurrentPackMax, Max);1077size_t StreamPos = S.getCurrentPosition();10781079// Print the first element in the pack. If Child contains a ParameterPack,1080// it will set up S.CurrentPackMax and print the first element.1081Child->print(S);10821083// No ParameterPack was found in Child. This can occur if we've found a pack1084// expansion on a <function-param>.1085if (S.CurrentPackMax == Max) {1086S += "...";1087return;1088}10891090// We found a ParameterPack, but it has no elements. Erase whatever we may1091// of printed.1092if (S.CurrentPackMax == 0) {1093S.setCurrentPosition(StreamPos);1094return;1095}10961097// Else, iterate through the rest of the elements in the pack.1098for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) {1099S += ", ";1100S.CurrentPackIndex = I;1101Child->print(S);1102}1103}1104};11051106class TemplateArgs final : public Node {1107NodeArray Params;11081109public:1110TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {}11111112template<typename Fn> void match(Fn F) const { F(Params); }11131114NodeArray getParams() { return Params; }11151116void printLeft(OutputStream &S) const override {1117S += "<";1118Params.printWithComma(S);1119if (S.back() == '>')1120S += " ";1121S += ">";1122}1123};11241125/// A forward-reference to a template argument that was not known at the point1126/// where the template parameter name was parsed in a mangling.1127///1128/// This is created when demangling the name of a specialization of a1129/// conversion function template:1130///1131/// \code1132/// struct A {1133/// template<typename T> operator T*();1134/// };1135/// \endcode1136///1137/// When demangling a specialization of the conversion function template, we1138/// encounter the name of the template (including the \c T) before we reach1139/// the template argument list, so we cannot substitute the parameter name1140/// for the corresponding argument while parsing. Instead, we create a1141/// \c ForwardTemplateReference node that is resolved after we parse the1142/// template arguments.1143struct ForwardTemplateReference : Node {1144size_t Index;1145Node *Ref = nullptr;11461147// If we're currently printing this node. It is possible (though invalid) for1148// a forward template reference to refer to itself via a substitution. This1149// creates a cyclic AST, which will stack overflow printing. To fix this, bail1150// out if more than one print* function is active.1151mutable bool Printing = false;11521153ForwardTemplateReference(size_t Index_)1154: Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown,1155Cache::Unknown),1156Index(Index_) {}11571158// We don't provide a matcher for these, because the value of the node is1159// not determined by its construction parameters, and it generally needs1160// special handling.1161template<typename Fn> void match(Fn F) const = delete;11621163bool hasRHSComponentSlow(OutputStream &S) const override {1164if (Printing)1165return false;1166SwapAndRestore<bool> SavePrinting(Printing, true);1167return Ref->hasRHSComponent(S);1168}1169bool hasArraySlow(OutputStream &S) const override {1170if (Printing)1171return false;1172SwapAndRestore<bool> SavePrinting(Printing, true);1173return Ref->hasArray(S);1174}1175bool hasFunctionSlow(OutputStream &S) const override {1176if (Printing)1177return false;1178SwapAndRestore<bool> SavePrinting(Printing, true);1179return Ref->hasFunction(S);1180}1181const Node *getSyntaxNode(OutputStream &S) const override {1182if (Printing)1183return this;1184SwapAndRestore<bool> SavePrinting(Printing, true);1185return Ref->getSyntaxNode(S);1186}11871188void printLeft(OutputStream &S) const override {1189if (Printing)1190return;1191SwapAndRestore<bool> SavePrinting(Printing, true);1192Ref->printLeft(S);1193}1194void printRight(OutputStream &S) const override {1195if (Printing)1196return;1197SwapAndRestore<bool> SavePrinting(Printing, true);1198Ref->printRight(S);1199}1200};12011202struct NameWithTemplateArgs : Node {1203// name<template_args>1204Node *Name;1205Node *TemplateArgs;12061207NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_)1208: Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {}12091210template<typename Fn> void match(Fn F) const { F(Name, TemplateArgs); }12111212StringView getBaseName() const override { return Name->getBaseName(); }12131214void printLeft(OutputStream &S) const override {1215Name->print(S);1216TemplateArgs->print(S);1217}1218};12191220class GlobalQualifiedName final : public Node {1221Node *Child;12221223public:1224GlobalQualifiedName(Node* Child_)1225: Node(KGlobalQualifiedName), Child(Child_) {}12261227template<typename Fn> void match(Fn F) const { F(Child); }12281229StringView getBaseName() const override { return Child->getBaseName(); }12301231void printLeft(OutputStream &S) const override {1232S += "::";1233Child->print(S);1234}1235};12361237struct StdQualifiedName : Node {1238Node *Child;12391240StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {}12411242template<typename Fn> void match(Fn F) const { F(Child); }12431244StringView getBaseName() const override { return Child->getBaseName(); }12451246void printLeft(OutputStream &S) const override {1247S += "std::";1248Child->print(S);1249}1250};12511252enum class SpecialSubKind {1253allocator,1254basic_string,1255string,1256istream,1257ostream,1258iostream,1259};12601261class ExpandedSpecialSubstitution final : public Node {1262SpecialSubKind SSK;12631264public:1265ExpandedSpecialSubstitution(SpecialSubKind SSK_)1266: Node(KExpandedSpecialSubstitution), SSK(SSK_) {}12671268template<typename Fn> void match(Fn F) const { F(SSK); }12691270StringView getBaseName() const override {1271switch (SSK) {1272case SpecialSubKind::allocator:1273return StringView("allocator");1274case SpecialSubKind::basic_string:1275return StringView("basic_string");1276case SpecialSubKind::string:1277return StringView("basic_string");1278case SpecialSubKind::istream:1279return StringView("basic_istream");1280case SpecialSubKind::ostream:1281return StringView("basic_ostream");1282case SpecialSubKind::iostream:1283return StringView("basic_iostream");1284}1285_LIBCPP_UNREACHABLE();1286}12871288void printLeft(OutputStream &S) const override {1289switch (SSK) {1290case SpecialSubKind::allocator:1291S += "std::allocator";1292break;1293case SpecialSubKind::basic_string:1294S += "std::basic_string";1295break;1296case SpecialSubKind::string:1297S += "std::basic_string<char, std::char_traits<char>, "1298"std::allocator<char> >";1299break;1300case SpecialSubKind::istream:1301S += "std::basic_istream<char, std::char_traits<char> >";1302break;1303case SpecialSubKind::ostream:1304S += "std::basic_ostream<char, std::char_traits<char> >";1305break;1306case SpecialSubKind::iostream:1307S += "std::basic_iostream<char, std::char_traits<char> >";1308break;1309}1310}1311};13121313class SpecialSubstitution final : public Node {1314public:1315SpecialSubKind SSK;13161317SpecialSubstitution(SpecialSubKind SSK_)1318: Node(KSpecialSubstitution), SSK(SSK_) {}13191320template<typename Fn> void match(Fn F) const { F(SSK); }13211322StringView getBaseName() const override {1323switch (SSK) {1324case SpecialSubKind::allocator:1325return StringView("allocator");1326case SpecialSubKind::basic_string:1327return StringView("basic_string");1328case SpecialSubKind::string:1329return StringView("string");1330case SpecialSubKind::istream:1331return StringView("istream");1332case SpecialSubKind::ostream:1333return StringView("ostream");1334case SpecialSubKind::iostream:1335return StringView("iostream");1336}1337_LIBCPP_UNREACHABLE();1338}13391340void printLeft(OutputStream &S) const override {1341switch (SSK) {1342case SpecialSubKind::allocator:1343S += "std::allocator";1344break;1345case SpecialSubKind::basic_string:1346S += "std::basic_string";1347break;1348case SpecialSubKind::string:1349S += "std::string";1350break;1351case SpecialSubKind::istream:1352S += "std::istream";1353break;1354case SpecialSubKind::ostream:1355S += "std::ostream";1356break;1357case SpecialSubKind::iostream:1358S += "std::iostream";1359break;1360}1361}1362};13631364class CtorDtorName final : public Node {1365const Node *Basename;1366const bool IsDtor;1367const int Variant;13681369public:1370CtorDtorName(const Node *Basename_, bool IsDtor_, int Variant_)1371: Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_),1372Variant(Variant_) {}13731374template<typename Fn> void match(Fn F) const { F(Basename, IsDtor, Variant); }13751376void printLeft(OutputStream &S) const override {1377if (IsDtor)1378S += "~";1379S += Basename->getBaseName();1380}1381};13821383class DtorName : public Node {1384const Node *Base;13851386public:1387DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {}13881389template<typename Fn> void match(Fn F) const { F(Base); }13901391void printLeft(OutputStream &S) const override {1392S += "~";1393Base->printLeft(S);1394}1395};13961397class UnnamedTypeName : public Node {1398const StringView Count;13991400public:1401UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {}14021403template<typename Fn> void match(Fn F) const { F(Count); }14041405void printLeft(OutputStream &S) const override {1406S += "'unnamed";1407S += Count;1408S += "\'";1409}1410};14111412class ClosureTypeName : public Node {1413NodeArray Params;1414StringView Count;14151416public:1417ClosureTypeName(NodeArray Params_, StringView Count_)1418: Node(KClosureTypeName), Params(Params_), Count(Count_) {}14191420template<typename Fn> void match(Fn F) const { F(Params, Count); }14211422void printLeft(OutputStream &S) const override {1423S += "\'lambda";1424S += Count;1425S += "\'(";1426Params.printWithComma(S);1427S += ")";1428}1429};14301431class StructuredBindingName : public Node {1432NodeArray Bindings;1433public:1434StructuredBindingName(NodeArray Bindings_)1435: Node(KStructuredBindingName), Bindings(Bindings_) {}14361437template<typename Fn> void match(Fn F) const { F(Bindings); }14381439void printLeft(OutputStream &S) const override {1440S += '[';1441Bindings.printWithComma(S);1442S += ']';1443}1444};14451446// -- Expression Nodes --14471448class BinaryExpr : public Node {1449const Node *LHS;1450const StringView InfixOperator;1451const Node *RHS;14521453public:1454BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_)1455: Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {1456}14571458template<typename Fn> void match(Fn F) const { F(LHS, InfixOperator, RHS); }14591460void printLeft(OutputStream &S) const override {1461// might be a template argument expression, then we need to disambiguate1462// with parens.1463if (InfixOperator == ">")1464S += "(";14651466S += "(";1467LHS->print(S);1468S += ") ";1469S += InfixOperator;1470S += " (";1471RHS->print(S);1472S += ")";14731474if (InfixOperator == ">")1475S += ")";1476}1477};14781479class ArraySubscriptExpr : public Node {1480const Node *Op1;1481const Node *Op2;14821483public:1484ArraySubscriptExpr(const Node *Op1_, const Node *Op2_)1485: Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {}14861487template<typename Fn> void match(Fn F) const { F(Op1, Op2); }14881489void printLeft(OutputStream &S) const override {1490S += "(";1491Op1->print(S);1492S += ")[";1493Op2->print(S);1494S += "]";1495}1496};14971498class PostfixExpr : public Node {1499const Node *Child;1500const StringView Operator;15011502public:1503PostfixExpr(const Node *Child_, StringView Operator_)1504: Node(KPostfixExpr), Child(Child_), Operator(Operator_) {}15051506template<typename Fn> void match(Fn F) const { F(Child, Operator); }15071508void printLeft(OutputStream &S) const override {1509S += "(";1510Child->print(S);1511S += ")";1512S += Operator;1513}1514};15151516class ConditionalExpr : public Node {1517const Node *Cond;1518const Node *Then;1519const Node *Else;15201521public:1522ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_)1523: Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {}15241525template<typename Fn> void match(Fn F) const { F(Cond, Then, Else); }15261527void printLeft(OutputStream &S) const override {1528S += "(";1529Cond->print(S);1530S += ") ? (";1531Then->print(S);1532S += ") : (";1533Else->print(S);1534S += ")";1535}1536};15371538class MemberExpr : public Node {1539const Node *LHS;1540const StringView Kind;1541const Node *RHS;15421543public:1544MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_)1545: Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {}15461547template<typename Fn> void match(Fn F) const { F(LHS, Kind, RHS); }15481549void printLeft(OutputStream &S) const override {1550LHS->print(S);1551S += Kind;1552RHS->print(S);1553}1554};15551556class EnclosingExpr : public Node {1557const StringView Prefix;1558const Node *Infix;1559const StringView Postfix;15601561public:1562EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_)1563: Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_),1564Postfix(Postfix_) {}15651566template<typename Fn> void match(Fn F) const { F(Prefix, Infix, Postfix); }15671568void printLeft(OutputStream &S) const override {1569S += Prefix;1570Infix->print(S);1571S += Postfix;1572}1573};15741575class CastExpr : public Node {1576// cast_kind<to>(from)1577const StringView CastKind;1578const Node *To;1579const Node *From;15801581public:1582CastExpr(StringView CastKind_, const Node *To_, const Node *From_)1583: Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {}15841585template<typename Fn> void match(Fn F) const { F(CastKind, To, From); }15861587void printLeft(OutputStream &S) const override {1588S += CastKind;1589S += "<";1590To->printLeft(S);1591S += ">(";1592From->printLeft(S);1593S += ")";1594}1595};15961597class SizeofParamPackExpr : public Node {1598const Node *Pack;15991600public:1601SizeofParamPackExpr(const Node *Pack_)1602: Node(KSizeofParamPackExpr), Pack(Pack_) {}16031604template<typename Fn> void match(Fn F) const { F(Pack); }16051606void printLeft(OutputStream &S) const override {1607S += "sizeof...(";1608ParameterPackExpansion PPE(Pack);1609PPE.printLeft(S);1610S += ")";1611}1612};16131614class CallExpr : public Node {1615const Node *Callee;1616NodeArray Args;16171618public:1619CallExpr(const Node *Callee_, NodeArray Args_)1620: Node(KCallExpr), Callee(Callee_), Args(Args_) {}16211622template<typename Fn> void match(Fn F) const { F(Callee, Args); }16231624void printLeft(OutputStream &S) const override {1625Callee->print(S);1626S += "(";1627Args.printWithComma(S);1628S += ")";1629}1630};16311632class NewExpr : public Node {1633// new (expr_list) type(init_list)1634NodeArray ExprList;1635Node *Type;1636NodeArray InitList;1637bool IsGlobal; // ::operator new ?1638bool IsArray; // new[] ?1639public:1640NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_,1641bool IsArray_)1642: Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_),1643IsGlobal(IsGlobal_), IsArray(IsArray_) {}16441645template<typename Fn> void match(Fn F) const {1646F(ExprList, Type, InitList, IsGlobal, IsArray);1647}16481649void printLeft(OutputStream &S) const override {1650if (IsGlobal)1651S += "::operator ";1652S += "new";1653if (IsArray)1654S += "[]";1655S += ' ';1656if (!ExprList.empty()) {1657S += "(";1658ExprList.printWithComma(S);1659S += ")";1660}1661Type->print(S);1662if (!InitList.empty()) {1663S += "(";1664InitList.printWithComma(S);1665S += ")";1666}16671668}1669};16701671class DeleteExpr : public Node {1672Node *Op;1673bool IsGlobal;1674bool IsArray;16751676public:1677DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_)1678: Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {}16791680template<typename Fn> void match(Fn F) const { F(Op, IsGlobal, IsArray); }16811682void printLeft(OutputStream &S) const override {1683if (IsGlobal)1684S += "::";1685S += "delete";1686if (IsArray)1687S += "[] ";1688Op->print(S);1689}1690};16911692class PrefixExpr : public Node {1693StringView Prefix;1694Node *Child;16951696public:1697PrefixExpr(StringView Prefix_, Node *Child_)1698: Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {}16991700template<typename Fn> void match(Fn F) const { F(Prefix, Child); }17011702void printLeft(OutputStream &S) const override {1703S += Prefix;1704S += "(";1705Child->print(S);1706S += ")";1707}1708};17091710class FunctionParam : public Node {1711StringView Number;17121713public:1714FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {}17151716template<typename Fn> void match(Fn F) const { F(Number); }17171718void printLeft(OutputStream &S) const override {1719S += "fp";1720S += Number;1721}1722};17231724class ConversionExpr : public Node {1725const Node *Type;1726NodeArray Expressions;17271728public:1729ConversionExpr(const Node *Type_, NodeArray Expressions_)1730: Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {}17311732template<typename Fn> void match(Fn F) const { F(Type, Expressions); }17331734void printLeft(OutputStream &S) const override {1735S += "(";1736Type->print(S);1737S += ")(";1738Expressions.printWithComma(S);1739S += ")";1740}1741};17421743class InitListExpr : public Node {1744const Node *Ty;1745NodeArray Inits;1746public:1747InitListExpr(const Node *Ty_, NodeArray Inits_)1748: Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {}17491750template<typename Fn> void match(Fn F) const { F(Ty, Inits); }17511752void printLeft(OutputStream &S) const override {1753if (Ty)1754Ty->print(S);1755S += '{';1756Inits.printWithComma(S);1757S += '}';1758}1759};17601761class BracedExpr : public Node {1762const Node *Elem;1763const Node *Init;1764bool IsArray;1765public:1766BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_)1767: Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {}17681769template<typename Fn> void match(Fn F) const { F(Elem, Init, IsArray); }17701771void printLeft(OutputStream &S) const override {1772if (IsArray) {1773S += '[';1774Elem->print(S);1775S += ']';1776} else {1777S += '.';1778Elem->print(S);1779}1780if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)1781S += " = ";1782Init->print(S);1783}1784};17851786class BracedRangeExpr : public Node {1787const Node *First;1788const Node *Last;1789const Node *Init;1790public:1791BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_)1792: Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {}17931794template<typename Fn> void match(Fn F) const { F(First, Last, Init); }17951796void printLeft(OutputStream &S) const override {1797S += '[';1798First->print(S);1799S += " ... ";1800Last->print(S);1801S += ']';1802if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr)1803S += " = ";1804Init->print(S);1805}1806};18071808class FoldExpr : public Node {1809const Node *Pack, *Init;1810StringView OperatorName;1811bool IsLeftFold;18121813public:1814FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_,1815const Node *Init_)1816: Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_),1817IsLeftFold(IsLeftFold_) {}18181819template<typename Fn> void match(Fn F) const {1820F(IsLeftFold, OperatorName, Pack, Init);1821}18221823void printLeft(OutputStream &S) const override {1824auto PrintPack = [&] {1825S += '(';1826ParameterPackExpansion(Pack).print(S);1827S += ')';1828};18291830S += '(';18311832if (IsLeftFold) {1833// init op ... op pack1834if (Init != nullptr) {1835Init->print(S);1836S += ' ';1837S += OperatorName;1838S += ' ';1839}1840// ... op pack1841S += "... ";1842S += OperatorName;1843S += ' ';1844PrintPack();1845} else { // !IsLeftFold1846// pack op ...1847PrintPack();1848S += ' ';1849S += OperatorName;1850S += " ...";1851// pack op ... op init1852if (Init != nullptr) {1853S += ' ';1854S += OperatorName;1855S += ' ';1856Init->print(S);1857}1858}1859S += ')';1860}1861};18621863class ThrowExpr : public Node {1864const Node *Op;18651866public:1867ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {}18681869template<typename Fn> void match(Fn F) const { F(Op); }18701871void printLeft(OutputStream &S) const override {1872S += "throw ";1873Op->print(S);1874}1875};18761877class BoolExpr : public Node {1878bool Value;18791880public:1881BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {}18821883template<typename Fn> void match(Fn F) const { F(Value); }18841885void printLeft(OutputStream &S) const override {1886S += Value ? StringView("true") : StringView("false");1887}1888};18891890class IntegerCastExpr : public Node {1891// ty(integer)1892const Node *Ty;1893StringView Integer;18941895public:1896IntegerCastExpr(const Node *Ty_, StringView Integer_)1897: Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}18981899template<typename Fn> void match(Fn F) const { F(Ty, Integer); }19001901void printLeft(OutputStream &S) const override {1902S += "(";1903Ty->print(S);1904S += ")";1905S += Integer;1906}1907};19081909class IntegerLiteral : public Node {1910StringView Type;1911StringView Value;19121913public:1914IntegerLiteral(StringView Type_, StringView Value_)1915: Node(KIntegerLiteral), Type(Type_), Value(Value_) {}19161917template<typename Fn> void match(Fn F) const { F(Type, Value); }19181919void printLeft(OutputStream &S) const override {1920if (Type.size() > 3) {1921S += "(";1922S += Type;1923S += ")";1924}19251926if (Value[0] == 'n') {1927S += "-";1928S += Value.dropFront(1);1929} else1930S += Value;19311932if (Type.size() <= 3)1933S += Type;1934}1935};19361937template <class Float> struct FloatData;19381939namespace float_literal_impl {1940constexpr Node::Kind getFloatLiteralKind(float *) {1941return Node::KFloatLiteral;1942}1943constexpr Node::Kind getFloatLiteralKind(double *) {1944return Node::KDoubleLiteral;1945}1946constexpr Node::Kind getFloatLiteralKind(long double *) {1947return Node::KLongDoubleLiteral;1948}1949}19501951template <class Float> class FloatLiteralImpl : public Node {1952const StringView Contents;19531954static constexpr Kind KindForClass =1955float_literal_impl::getFloatLiteralKind((Float *)nullptr);19561957public:1958FloatLiteralImpl(StringView Contents_)1959: Node(KindForClass), Contents(Contents_) {}19601961template<typename Fn> void match(Fn F) const { F(Contents); }19621963void printLeft(OutputStream &s) const override {1964const char *first = Contents.begin();1965const char *last = Contents.end() + 1;19661967const size_t N = FloatData<Float>::mangled_size;1968if (static_cast<std::size_t>(last - first) > N) {1969last = first + N;1970union {1971Float value;1972char buf[sizeof(Float)];1973};1974const char *t = first;1975char *e = buf;1976for (; t != last; ++t, ++e) {1977unsigned d1 = isdigit(*t) ? static_cast<unsigned>(*t - '0')1978: static_cast<unsigned>(*t - 'a' + 10);1979++t;1980unsigned d0 = isdigit(*t) ? static_cast<unsigned>(*t - '0')1981: static_cast<unsigned>(*t - 'a' + 10);1982*e = static_cast<char>((d1 << 4) + d0);1983}1984#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__1985std::reverse(buf, e);1986#endif1987char num[FloatData<Float>::max_demangled_size] = {0};1988int n = snprintf(num, sizeof(num), FloatData<Float>::spec, value);1989s += StringView(num, num + n);1990}1991}1992};19931994using FloatLiteral = FloatLiteralImpl<float>;1995using DoubleLiteral = FloatLiteralImpl<double>;1996using LongDoubleLiteral = FloatLiteralImpl<long double>;19971998/// Visit the node. Calls \c F(P), where \c P is the node cast to the1999/// appropriate derived class.2000template<typename Fn>2001void Node::visit(Fn F) const {2002switch (K) {2003#define CASE(X) case K ## X: return F(static_cast<const X*>(this));2004FOR_EACH_NODE_KIND(CASE)2005#undef CASE2006}2007assert(0 && "unknown mangling node kind");2008}20092010/// Determine the kind of a node from its type.2011template<typename NodeT> struct NodeKind;2012#define SPECIALIZATION(X) \2013template<> struct NodeKind<X> { \2014static constexpr Node::Kind Kind = Node::K##X; \2015static constexpr const char *name() { return #X; } \2016};2017FOR_EACH_NODE_KIND(SPECIALIZATION)2018#undef SPECIALIZATION20192020#undef FOR_EACH_NODE_KIND20212022template <class T, size_t N>2023class PODSmallVector {2024static_assert(std::is_pod<T>::value,2025"T is required to be a plain old data type");20262027T* First;2028T* Last;2029T* Cap;2030T Inline[N];20312032bool isInline() const { return First == Inline; }20332034void clearInline() {2035First = Inline;2036Last = Inline;2037Cap = Inline + N;2038}20392040void reserve(size_t NewCap) {2041size_t S = size();2042if (isInline()) {2043auto* Tmp = static_cast<T*>(std::malloc(NewCap * sizeof(T)));2044if (Tmp == nullptr)2045std::terminate();2046std::copy(First, Last, Tmp);2047First = Tmp;2048} else {2049First = static_cast<T*>(std::realloc(First, NewCap * sizeof(T)));2050if (First == nullptr)2051std::terminate();2052}2053Last = First + S;2054Cap = First + NewCap;2055}20562057public:2058PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {}20592060PODSmallVector(const PODSmallVector&) = delete;2061PODSmallVector& operator=(const PODSmallVector&) = delete;20622063PODSmallVector(PODSmallVector&& Other) : PODSmallVector() {2064if (Other.isInline()) {2065std::copy(Other.begin(), Other.end(), First);2066Last = First + Other.size();2067Other.clear();2068return;2069}20702071First = Other.First;2072Last = Other.Last;2073Cap = Other.Cap;2074Other.clearInline();2075}20762077PODSmallVector& operator=(PODSmallVector&& Other) {2078if (Other.isInline()) {2079if (!isInline()) {2080std::free(First);2081clearInline();2082}2083std::copy(Other.begin(), Other.end(), First);2084Last = First + Other.size();2085Other.clear();2086return *this;2087}20882089if (isInline()) {2090First = Other.First;2091Last = Other.Last;2092Cap = Other.Cap;2093Other.clearInline();2094return *this;2095}20962097std::swap(First, Other.First);2098std::swap(Last, Other.Last);2099std::swap(Cap, Other.Cap);2100Other.clear();2101return *this;2102}21032104void push_back(const T& Elem) {2105if (Last == Cap)2106reserve(size() * 2);2107*Last++ = Elem;2108}21092110void pop_back() {2111assert(Last != First && "Popping empty vector!");2112--Last;2113}21142115void dropBack(size_t Index) {2116assert(Index <= size() && "dropBack() can't expand!");2117Last = First + Index;2118}21192120T* begin() { return First; }2121T* end() { return Last; }21222123bool empty() const { return First == Last; }2124size_t size() const { return static_cast<size_t>(Last - First); }2125T& back() {2126assert(Last != First && "Calling back() on empty vector!");2127return *(Last - 1);2128}2129T& operator[](size_t Index) {2130assert(Index < size() && "Invalid access!");2131return *(begin() + Index);2132}2133void clear() { Last = First; }21342135~PODSmallVector() {2136if (!isInline())2137std::free(First);2138}2139};21402141template <typename Derived, typename Alloc> struct AbstractManglingParser {2142const char *First;2143const char *Last;21442145// Name stack, this is used by the parser to hold temporary names that were2146// parsed. The parser collapses multiple names into new nodes to construct2147// the AST. Once the parser is finished, names.size() == 1.2148PODSmallVector<Node *, 32> Names;21492150// Substitution table. Itanium supports name substitutions as a means of2151// compression. The string "S42_" refers to the 44nd entry (base-36) in this2152// table.2153PODSmallVector<Node *, 32> Subs;21542155// Template parameter table. Like the above, but referenced like "T42_".2156// This has a smaller size compared to Subs and Names because it can be2157// stored on the stack.2158PODSmallVector<Node *, 8> TemplateParams;21592160// Set of unresolved forward <template-param> references. These can occur in a2161// conversion operator's type, and are resolved in the enclosing <encoding>.2162PODSmallVector<ForwardTemplateReference *, 4> ForwardTemplateRefs;21632164bool TryToParseTemplateArgs = true;2165bool PermitForwardTemplateReferences = false;2166bool ParsingLambdaParams = false;21672168Alloc ASTAllocator;21692170AbstractManglingParser(const char *First_, const char *Last_)2171: First(First_), Last(Last_) {}21722173Derived &getDerived() { return static_cast<Derived &>(*this); }21742175void reset(const char *First_, const char *Last_) {2176First = First_;2177Last = Last_;2178Names.clear();2179Subs.clear();2180TemplateParams.clear();2181ParsingLambdaParams = false;2182TryToParseTemplateArgs = true;2183PermitForwardTemplateReferences = false;2184ASTAllocator.reset();2185}21862187template <class T, class... Args> Node *make(Args &&... args) {2188return ASTAllocator.template makeNode<T>(std::forward<Args>(args)...);2189}21902191template <class It> NodeArray makeNodeArray(It begin, It end) {2192size_t sz = static_cast<size_t>(end - begin);2193void *mem = ASTAllocator.allocateNodeArray(sz);2194Node **data = new (mem) Node *[sz];2195std::copy(begin, end, data);2196return NodeArray(data, sz);2197}21982199NodeArray popTrailingNodeArray(size_t FromPosition) {2200assert(FromPosition <= Names.size());2201NodeArray res =2202makeNodeArray(Names.begin() + (long)FromPosition, Names.end());2203Names.dropBack(FromPosition);2204return res;2205}22062207bool consumeIf(StringView S) {2208if (StringView(First, Last).startsWith(S)) {2209First += S.size();2210return true;2211}2212return false;2213}22142215bool consumeIf(char C) {2216if (First != Last && *First == C) {2217++First;2218return true;2219}2220return false;2221}22222223char consume() { return First != Last ? *First++ : '\0'; }22242225char look(unsigned Lookahead = 0) {2226if (static_cast<size_t>(Last - First) <= Lookahead)2227return '\0';2228return First[Lookahead];2229}22302231size_t numLeft() const { return static_cast<size_t>(Last - First); }22322233StringView parseNumber(bool AllowNegative = false);2234Qualifiers parseCVQualifiers();2235bool parsePositiveInteger(size_t *Out);2236StringView parseBareSourceName();22372238bool parseSeqId(size_t *Out);2239Node *parseSubstitution();2240Node *parseTemplateParam();2241Node *parseTemplateArgs(bool TagTemplates = false);2242Node *parseTemplateArg();22432244/// Parse the <expr> production.2245Node *parseExpr();2246Node *parsePrefixExpr(StringView Kind);2247Node *parseBinaryExpr(StringView Kind);2248Node *parseIntegerLiteral(StringView Lit);2249Node *parseExprPrimary();2250template <class Float> Node *parseFloatingLiteral();2251Node *parseFunctionParam();2252Node *parseNewExpr();2253Node *parseConversionExpr();2254Node *parseBracedExpr();2255Node *parseFoldExpr();22562257/// Parse the <type> production.2258Node *parseType();2259Node *parseFunctionType();2260Node *parseVectorType();2261Node *parseDecltype();2262Node *parseArrayType();2263Node *parsePointerToMemberType();2264Node *parseClassEnumType();2265Node *parseQualifiedType();22662267Node *parseEncoding();2268bool parseCallOffset();2269Node *parseSpecialName();22702271/// Holds some extra information about a <name> that is being parsed. This2272/// information is only pertinent if the <name> refers to an <encoding>.2273struct NameState {2274bool CtorDtorConversion = false;2275bool EndsWithTemplateArgs = false;2276Qualifiers CVQualifiers = QualNone;2277FunctionRefQual ReferenceQualifier = FrefQualNone;2278size_t ForwardTemplateRefsBegin;22792280NameState(AbstractManglingParser *Enclosing)2281: ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {}2282};22832284bool resolveForwardTemplateRefs(NameState &State) {2285size_t I = State.ForwardTemplateRefsBegin;2286size_t E = ForwardTemplateRefs.size();2287for (; I < E; ++I) {2288size_t Idx = ForwardTemplateRefs[I]->Index;2289if (Idx >= TemplateParams.size())2290return true;2291ForwardTemplateRefs[I]->Ref = TemplateParams[Idx];2292}2293ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin);2294return false;2295}22962297/// Parse the <name> production>2298Node *parseName(NameState *State = nullptr);2299Node *parseLocalName(NameState *State);2300Node *parseOperatorName(NameState *State);2301Node *parseUnqualifiedName(NameState *State);2302Node *parseUnnamedTypeName(NameState *State);2303Node *parseSourceName(NameState *State);2304Node *parseUnscopedName(NameState *State);2305Node *parseNestedName(NameState *State);2306Node *parseCtorDtorName(Node *&SoFar, NameState *State);23072308Node *parseAbiTags(Node *N);23092310/// Parse the <unresolved-name> production.2311Node *parseUnresolvedName();2312Node *parseSimpleId();2313Node *parseBaseUnresolvedName();2314Node *parseUnresolvedType();2315Node *parseDestructorName();23162317/// Top-level entry point into the parser.2318Node *parse();2319};23202321const char* parse_discriminator(const char* first, const char* last);23222323// <name> ::= <nested-name> // N2324// ::= <local-name> # See Scope Encoding below // Z2325// ::= <unscoped-template-name> <template-args>2326// ::= <unscoped-name>2327//2328// <unscoped-template-name> ::= <unscoped-name>2329// ::= <substitution>2330template <typename Derived, typename Alloc>2331Node *AbstractManglingParser<Derived, Alloc>::parseName(NameState *State) {2332consumeIf('L'); // extension23332334if (look() == 'N')2335return getDerived().parseNestedName(State);2336if (look() == 'Z')2337return getDerived().parseLocalName(State);23382339// ::= <unscoped-template-name> <template-args>2340if (look() == 'S' && look(1) != 't') {2341Node *S = getDerived().parseSubstitution();2342if (S == nullptr)2343return nullptr;2344if (look() != 'I')2345return nullptr;2346Node *TA = getDerived().parseTemplateArgs(State != nullptr);2347if (TA == nullptr)2348return nullptr;2349if (State) State->EndsWithTemplateArgs = true;2350return make<NameWithTemplateArgs>(S, TA);2351}23522353Node *N = getDerived().parseUnscopedName(State);2354if (N == nullptr)2355return nullptr;2356// ::= <unscoped-template-name> <template-args>2357if (look() == 'I') {2358Subs.push_back(N);2359Node *TA = getDerived().parseTemplateArgs(State != nullptr);2360if (TA == nullptr)2361return nullptr;2362if (State) State->EndsWithTemplateArgs = true;2363return make<NameWithTemplateArgs>(N, TA);2364}2365// ::= <unscoped-name>2366return N;2367}23682369// <local-name> := Z <function encoding> E <entity name> [<discriminator>]2370// := Z <function encoding> E s [<discriminator>]2371// := Z <function encoding> Ed [ <parameter number> ] _ <entity name>2372template <typename Derived, typename Alloc>2373Node *AbstractManglingParser<Derived, Alloc>::parseLocalName(NameState *State) {2374if (!consumeIf('Z'))2375return nullptr;2376Node *Encoding = getDerived().parseEncoding();2377if (Encoding == nullptr || !consumeIf('E'))2378return nullptr;23792380if (consumeIf('s')) {2381First = parse_discriminator(First, Last);2382auto *StringLitName = make<NameType>("string literal");2383if (!StringLitName)2384return nullptr;2385return make<LocalName>(Encoding, StringLitName);2386}23872388if (consumeIf('d')) {2389parseNumber(true);2390if (!consumeIf('_'))2391return nullptr;2392Node *N = getDerived().parseName(State);2393if (N == nullptr)2394return nullptr;2395return make<LocalName>(Encoding, N);2396}23972398Node *Entity = getDerived().parseName(State);2399if (Entity == nullptr)2400return nullptr;2401First = parse_discriminator(First, Last);2402return make<LocalName>(Encoding, Entity);2403}24042405// <unscoped-name> ::= <unqualified-name>2406// ::= St <unqualified-name> # ::std::2407// extension ::= StL<unqualified-name>2408template <typename Derived, typename Alloc>2409Node *2410AbstractManglingParser<Derived, Alloc>::parseUnscopedName(NameState *State) {2411if (consumeIf("StL") || consumeIf("St")) {2412Node *R = getDerived().parseUnqualifiedName(State);2413if (R == nullptr)2414return nullptr;2415return make<StdQualifiedName>(R);2416}2417return getDerived().parseUnqualifiedName(State);2418}24192420// <unqualified-name> ::= <operator-name> [abi-tags]2421// ::= <ctor-dtor-name>2422// ::= <source-name>2423// ::= <unnamed-type-name>2424// ::= DC <source-name>+ E # structured binding declaration2425template <typename Derived, typename Alloc>2426Node *2427AbstractManglingParser<Derived, Alloc>::parseUnqualifiedName(NameState *State) {2428// <ctor-dtor-name>s are special-cased in parseNestedName().2429Node *Result;2430if (look() == 'U')2431Result = getDerived().parseUnnamedTypeName(State);2432else if (look() >= '1' && look() <= '9')2433Result = getDerived().parseSourceName(State);2434else if (consumeIf("DC")) {2435size_t BindingsBegin = Names.size();2436do {2437Node *Binding = getDerived().parseSourceName(State);2438if (Binding == nullptr)2439return nullptr;2440Names.push_back(Binding);2441} while (!consumeIf('E'));2442Result = make<StructuredBindingName>(popTrailingNodeArray(BindingsBegin));2443} else2444Result = getDerived().parseOperatorName(State);2445if (Result != nullptr)2446Result = getDerived().parseAbiTags(Result);2447return Result;2448}24492450// <unnamed-type-name> ::= Ut [<nonnegative number>] _2451// ::= <closure-type-name>2452//2453// <closure-type-name> ::= Ul <lambda-sig> E [ <nonnegative number> ] _2454//2455// <lambda-sig> ::= <parameter type>+ # Parameter types or "v" if the lambda has no parameters2456template <typename Derived, typename Alloc>2457Node *2458AbstractManglingParser<Derived, Alloc>::parseUnnamedTypeName(NameState *) {2459if (consumeIf("Ut")) {2460StringView Count = parseNumber();2461if (!consumeIf('_'))2462return nullptr;2463return make<UnnamedTypeName>(Count);2464}2465if (consumeIf("Ul")) {2466NodeArray Params;2467SwapAndRestore<bool> SwapParams(ParsingLambdaParams, true);2468if (!consumeIf("vE")) {2469size_t ParamsBegin = Names.size();2470do {2471Node *P = getDerived().parseType();2472if (P == nullptr)2473return nullptr;2474Names.push_back(P);2475} while (!consumeIf('E'));2476Params = popTrailingNodeArray(ParamsBegin);2477}2478StringView Count = parseNumber();2479if (!consumeIf('_'))2480return nullptr;2481return make<ClosureTypeName>(Params, Count);2482}2483return nullptr;2484}24852486// <source-name> ::= <positive length number> <identifier>2487template <typename Derived, typename Alloc>2488Node *AbstractManglingParser<Derived, Alloc>::parseSourceName(NameState *) {2489size_t Length = 0;2490if (parsePositiveInteger(&Length))2491return nullptr;2492if (numLeft() < Length || Length == 0)2493return nullptr;2494StringView Name(First, First + Length);2495First += Length;2496if (Name.startsWith("_GLOBAL__N"))2497return make<NameType>("(anonymous namespace)");2498return make<NameType>(Name);2499}25002501// <operator-name> ::= aa # &&2502// ::= ad # & (unary)2503// ::= an # &2504// ::= aN # &=2505// ::= aS # =2506// ::= cl # ()2507// ::= cm # ,2508// ::= co # ~2509// ::= cv <type> # (cast)2510// ::= da # delete[]2511// ::= de # * (unary)2512// ::= dl # delete2513// ::= dv # /2514// ::= dV # /=2515// ::= eo # ^2516// ::= eO # ^=2517// ::= eq # ==2518// ::= ge # >=2519// ::= gt # >2520// ::= ix # []2521// ::= le # <=2522// ::= li <source-name> # operator ""2523// ::= ls # <<2524// ::= lS # <<=2525// ::= lt # <2526// ::= mi # -2527// ::= mI # -=2528// ::= ml # *2529// ::= mL # *=2530// ::= mm # -- (postfix in <expression> context)2531// ::= na # new[]2532// ::= ne # !=2533// ::= ng # - (unary)2534// ::= nt # !2535// ::= nw # new2536// ::= oo # ||2537// ::= or # |2538// ::= oR # |=2539// ::= pm # ->*2540// ::= pl # +2541// ::= pL # +=2542// ::= pp # ++ (postfix in <expression> context)2543// ::= ps # + (unary)2544// ::= pt # ->2545// ::= qu # ?2546// ::= rm # %2547// ::= rM # %=2548// ::= rs # >>2549// ::= rS # >>=2550// ::= ss # <=> C++2a2551// ::= v <digit> <source-name> # vendor extended operator2552template <typename Derived, typename Alloc>2553Node *2554AbstractManglingParser<Derived, Alloc>::parseOperatorName(NameState *State) {2555switch (look()) {2556case 'a':2557switch (look(1)) {2558case 'a':2559First += 2;2560return make<NameType>("operator&&");2561case 'd':2562case 'n':2563First += 2;2564return make<NameType>("operator&");2565case 'N':2566First += 2;2567return make<NameType>("operator&=");2568case 'S':2569First += 2;2570return make<NameType>("operator=");2571}2572return nullptr;2573case 'c':2574switch (look(1)) {2575case 'l':2576First += 2;2577return make<NameType>("operator()");2578case 'm':2579First += 2;2580return make<NameType>("operator,");2581case 'o':2582First += 2;2583return make<NameType>("operator~");2584// ::= cv <type> # (cast)2585case 'v': {2586First += 2;2587SwapAndRestore<bool> SaveTemplate(TryToParseTemplateArgs, false);2588// If we're parsing an encoding, State != nullptr and the conversion2589// operators' <type> could have a <template-param> that refers to some2590// <template-arg>s further ahead in the mangled name.2591SwapAndRestore<bool> SavePermit(PermitForwardTemplateReferences,2592PermitForwardTemplateReferences ||2593State != nullptr);2594Node *Ty = getDerived().parseType();2595if (Ty == nullptr)2596return nullptr;2597if (State) State->CtorDtorConversion = true;2598return make<ConversionOperatorType>(Ty);2599}2600}2601return nullptr;2602case 'd':2603switch (look(1)) {2604case 'a':2605First += 2;2606return make<NameType>("operator delete[]");2607case 'e':2608First += 2;2609return make<NameType>("operator*");2610case 'l':2611First += 2;2612return make<NameType>("operator delete");2613case 'v':2614First += 2;2615return make<NameType>("operator/");2616case 'V':2617First += 2;2618return make<NameType>("operator/=");2619}2620return nullptr;2621case 'e':2622switch (look(1)) {2623case 'o':2624First += 2;2625return make<NameType>("operator^");2626case 'O':2627First += 2;2628return make<NameType>("operator^=");2629case 'q':2630First += 2;2631return make<NameType>("operator==");2632}2633return nullptr;2634case 'g':2635switch (look(1)) {2636case 'e':2637First += 2;2638return make<NameType>("operator>=");2639case 't':2640First += 2;2641return make<NameType>("operator>");2642}2643return nullptr;2644case 'i':2645if (look(1) == 'x') {2646First += 2;2647return make<NameType>("operator[]");2648}2649return nullptr;2650case 'l':2651switch (look(1)) {2652case 'e':2653First += 2;2654return make<NameType>("operator<=");2655// ::= li <source-name> # operator ""2656case 'i': {2657First += 2;2658Node *SN = getDerived().parseSourceName(State);2659if (SN == nullptr)2660return nullptr;2661return make<LiteralOperator>(SN);2662}2663case 's':2664First += 2;2665return make<NameType>("operator<<");2666case 'S':2667First += 2;2668return make<NameType>("operator<<=");2669case 't':2670First += 2;2671return make<NameType>("operator<");2672}2673return nullptr;2674case 'm':2675switch (look(1)) {2676case 'i':2677First += 2;2678return make<NameType>("operator-");2679case 'I':2680First += 2;2681return make<NameType>("operator-=");2682case 'l':2683First += 2;2684return make<NameType>("operator*");2685case 'L':2686First += 2;2687return make<NameType>("operator*=");2688case 'm':2689First += 2;2690return make<NameType>("operator--");2691}2692return nullptr;2693case 'n':2694switch (look(1)) {2695case 'a':2696First += 2;2697return make<NameType>("operator new[]");2698case 'e':2699First += 2;2700return make<NameType>("operator!=");2701case 'g':2702First += 2;2703return make<NameType>("operator-");2704case 't':2705First += 2;2706return make<NameType>("operator!");2707case 'w':2708First += 2;2709return make<NameType>("operator new");2710}2711return nullptr;2712case 'o':2713switch (look(1)) {2714case 'o':2715First += 2;2716return make<NameType>("operator||");2717case 'r':2718First += 2;2719return make<NameType>("operator|");2720case 'R':2721First += 2;2722return make<NameType>("operator|=");2723}2724return nullptr;2725case 'p':2726switch (look(1)) {2727case 'm':2728First += 2;2729return make<NameType>("operator->*");2730case 'l':2731First += 2;2732return make<NameType>("operator+");2733case 'L':2734First += 2;2735return make<NameType>("operator+=");2736case 'p':2737First += 2;2738return make<NameType>("operator++");2739case 's':2740First += 2;2741return make<NameType>("operator+");2742case 't':2743First += 2;2744return make<NameType>("operator->");2745}2746return nullptr;2747case 'q':2748if (look(1) == 'u') {2749First += 2;2750return make<NameType>("operator?");2751}2752return nullptr;2753case 'r':2754switch (look(1)) {2755case 'm':2756First += 2;2757return make<NameType>("operator%");2758case 'M':2759First += 2;2760return make<NameType>("operator%=");2761case 's':2762First += 2;2763return make<NameType>("operator>>");2764case 'S':2765First += 2;2766return make<NameType>("operator>>=");2767}2768return nullptr;2769case 's':2770if (look(1) == 's') {2771First += 2;2772return make<NameType>("operator<=>");2773}2774return nullptr;2775// ::= v <digit> <source-name> # vendor extended operator2776case 'v':2777if (std::isdigit(look(1))) {2778First += 2;2779Node *SN = getDerived().parseSourceName(State);2780if (SN == nullptr)2781return nullptr;2782return make<ConversionOperatorType>(SN);2783}2784return nullptr;2785}2786return nullptr;2787}27882789// <ctor-dtor-name> ::= C1 # complete object constructor2790// ::= C2 # base object constructor2791// ::= C3 # complete object allocating constructor2792// extension ::= C5 # ?2793// ::= D0 # deleting destructor2794// ::= D1 # complete object destructor2795// ::= D2 # base object destructor2796// extension ::= D5 # ?2797template <typename Derived, typename Alloc>2798Node *2799AbstractManglingParser<Derived, Alloc>::parseCtorDtorName(Node *&SoFar,2800NameState *State) {2801if (SoFar->getKind() == Node::KSpecialSubstitution) {2802auto SSK = static_cast<SpecialSubstitution *>(SoFar)->SSK;2803switch (SSK) {2804case SpecialSubKind::string:2805case SpecialSubKind::istream:2806case SpecialSubKind::ostream:2807case SpecialSubKind::iostream:2808SoFar = make<ExpandedSpecialSubstitution>(SSK);2809if (!SoFar)2810return nullptr;2811break;2812default:2813break;2814}2815}28162817if (consumeIf('C')) {2818bool IsInherited = consumeIf('I');2819if (look() != '1' && look() != '2' && look() != '3' && look() != '5')2820return nullptr;2821int Variant = look() - '0';2822++First;2823if (State) State->CtorDtorConversion = true;2824if (IsInherited) {2825if (getDerived().parseName(State) == nullptr)2826return nullptr;2827}2828return make<CtorDtorName>(SoFar, false, Variant);2829}28302831if (look() == 'D' &&2832(look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) {2833int Variant = look(1) - '0';2834First += 2;2835if (State) State->CtorDtorConversion = true;2836return make<CtorDtorName>(SoFar, true, Variant);2837}28382839return nullptr;2840}28412842// <nested-name> ::= N [<CV-Qualifiers>] [<ref-qualifier>] <prefix> <unqualified-name> E2843// ::= N [<CV-Qualifiers>] [<ref-qualifier>] <template-prefix> <template-args> E2844//2845// <prefix> ::= <prefix> <unqualified-name>2846// ::= <template-prefix> <template-args>2847// ::= <template-param>2848// ::= <decltype>2849// ::= # empty2850// ::= <substitution>2851// ::= <prefix> <data-member-prefix>2852// extension ::= L2853//2854// <data-member-prefix> := <member source-name> [<template-args>] M2855//2856// <template-prefix> ::= <prefix> <template unqualified-name>2857// ::= <template-param>2858// ::= <substitution>2859template <typename Derived, typename Alloc>2860Node *2861AbstractManglingParser<Derived, Alloc>::parseNestedName(NameState *State) {2862if (!consumeIf('N'))2863return nullptr;28642865Qualifiers CVTmp = parseCVQualifiers();2866if (State) State->CVQualifiers = CVTmp;28672868if (consumeIf('O')) {2869if (State) State->ReferenceQualifier = FrefQualRValue;2870} else if (consumeIf('R')) {2871if (State) State->ReferenceQualifier = FrefQualLValue;2872} else2873if (State) State->ReferenceQualifier = FrefQualNone;28742875Node *SoFar = nullptr;2876auto PushComponent = [&](Node *Comp) {2877if (!Comp) return false;2878if (SoFar) SoFar = make<NestedName>(SoFar, Comp);2879else SoFar = Comp;2880if (State) State->EndsWithTemplateArgs = false;2881return SoFar != nullptr;2882};28832884if (consumeIf("St")) {2885SoFar = make<NameType>("std");2886if (!SoFar)2887return nullptr;2888}28892890while (!consumeIf('E')) {2891consumeIf('L'); // extension28922893// <data-member-prefix> := <member source-name> [<template-args>] M2894if (consumeIf('M')) {2895if (SoFar == nullptr)2896return nullptr;2897continue;2898}28992900// ::= <template-param>2901if (look() == 'T') {2902if (!PushComponent(getDerived().parseTemplateParam()))2903return nullptr;2904Subs.push_back(SoFar);2905continue;2906}29072908// ::= <template-prefix> <template-args>2909if (look() == 'I') {2910Node *TA = getDerived().parseTemplateArgs(State != nullptr);2911if (TA == nullptr || SoFar == nullptr)2912return nullptr;2913SoFar = make<NameWithTemplateArgs>(SoFar, TA);2914if (!SoFar)2915return nullptr;2916if (State) State->EndsWithTemplateArgs = true;2917Subs.push_back(SoFar);2918continue;2919}29202921// ::= <decltype>2922if (look() == 'D' && (look(1) == 't' || look(1) == 'T')) {2923if (!PushComponent(getDerived().parseDecltype()))2924return nullptr;2925Subs.push_back(SoFar);2926continue;2927}29282929// ::= <substitution>2930if (look() == 'S' && look(1) != 't') {2931Node *S = getDerived().parseSubstitution();2932if (!PushComponent(S))2933return nullptr;2934if (SoFar != S)2935Subs.push_back(S);2936continue;2937}29382939// Parse an <unqualified-name> thats actually a <ctor-dtor-name>.2940if (look() == 'C' || (look() == 'D' && look(1) != 'C')) {2941if (SoFar == nullptr)2942return nullptr;2943if (!PushComponent(getDerived().parseCtorDtorName(SoFar, State)))2944return nullptr;2945SoFar = getDerived().parseAbiTags(SoFar);2946if (SoFar == nullptr)2947return nullptr;2948Subs.push_back(SoFar);2949continue;2950}29512952// ::= <prefix> <unqualified-name>2953if (!PushComponent(getDerived().parseUnqualifiedName(State)))2954return nullptr;2955Subs.push_back(SoFar);2956}29572958if (SoFar == nullptr || Subs.empty())2959return nullptr;29602961Subs.pop_back();2962return SoFar;2963}29642965// <simple-id> ::= <source-name> [ <template-args> ]2966template <typename Derived, typename Alloc>2967Node *AbstractManglingParser<Derived, Alloc>::parseSimpleId() {2968Node *SN = getDerived().parseSourceName(/*NameState=*/nullptr);2969if (SN == nullptr)2970return nullptr;2971if (look() == 'I') {2972Node *TA = getDerived().parseTemplateArgs();2973if (TA == nullptr)2974return nullptr;2975return make<NameWithTemplateArgs>(SN, TA);2976}2977return SN;2978}29792980// <destructor-name> ::= <unresolved-type> # e.g., ~T or ~decltype(f())2981// ::= <simple-id> # e.g., ~A<2*N>2982template <typename Derived, typename Alloc>2983Node *AbstractManglingParser<Derived, Alloc>::parseDestructorName() {2984Node *Result;2985if (std::isdigit(look()))2986Result = getDerived().parseSimpleId();2987else2988Result = getDerived().parseUnresolvedType();2989if (Result == nullptr)2990return nullptr;2991return make<DtorName>(Result);2992}29932994// <unresolved-type> ::= <template-param>2995// ::= <decltype>2996// ::= <substitution>2997template <typename Derived, typename Alloc>2998Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedType() {2999if (look() == 'T') {3000Node *TP = getDerived().parseTemplateParam();3001if (TP == nullptr)3002return nullptr;3003Subs.push_back(TP);3004return TP;3005}3006if (look() == 'D') {3007Node *DT = getDerived().parseDecltype();3008if (DT == nullptr)3009return nullptr;3010Subs.push_back(DT);3011return DT;3012}3013return getDerived().parseSubstitution();3014}30153016// <base-unresolved-name> ::= <simple-id> # unresolved name3017// extension ::= <operator-name> # unresolved operator-function-id3018// extension ::= <operator-name> <template-args> # unresolved operator template-id3019// ::= on <operator-name> # unresolved operator-function-id3020// ::= on <operator-name> <template-args> # unresolved operator template-id3021// ::= dn <destructor-name> # destructor or pseudo-destructor;3022// # e.g. ~X or ~X<N-1>3023template <typename Derived, typename Alloc>3024Node *AbstractManglingParser<Derived, Alloc>::parseBaseUnresolvedName() {3025if (std::isdigit(look()))3026return getDerived().parseSimpleId();30273028if (consumeIf("dn"))3029return getDerived().parseDestructorName();30303031consumeIf("on");30323033Node *Oper = getDerived().parseOperatorName(/*NameState=*/nullptr);3034if (Oper == nullptr)3035return nullptr;3036if (look() == 'I') {3037Node *TA = getDerived().parseTemplateArgs();3038if (TA == nullptr)3039return nullptr;3040return make<NameWithTemplateArgs>(Oper, TA);3041}3042return Oper;3043}30443045// <unresolved-name>3046// extension ::= srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3047// ::= [gs] <base-unresolved-name> # x or (with "gs") ::x3048// ::= [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3049// # A::x, N::y, A<T>::z; "gs" means leading "::"3050// ::= sr <unresolved-type> <base-unresolved-name> # T::x / decltype(p)::x3051// extension ::= sr <unresolved-type> <template-args> <base-unresolved-name>3052// # T::N::x /decltype(p)::N::x3053// (ignored) ::= srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3054//3055// <unresolved-qualifier-level> ::= <simple-id>3056template <typename Derived, typename Alloc>3057Node *AbstractManglingParser<Derived, Alloc>::parseUnresolvedName() {3058Node *SoFar = nullptr;30593060// srN <unresolved-type> [<template-args>] <unresolved-qualifier-level>* E <base-unresolved-name>3061// srN <unresolved-type> <unresolved-qualifier-level>+ E <base-unresolved-name>3062if (consumeIf("srN")) {3063SoFar = getDerived().parseUnresolvedType();3064if (SoFar == nullptr)3065return nullptr;30663067if (look() == 'I') {3068Node *TA = getDerived().parseTemplateArgs();3069if (TA == nullptr)3070return nullptr;3071SoFar = make<NameWithTemplateArgs>(SoFar, TA);3072if (!SoFar)3073return nullptr;3074}30753076while (!consumeIf('E')) {3077Node *Qual = getDerived().parseSimpleId();3078if (Qual == nullptr)3079return nullptr;3080SoFar = make<QualifiedName>(SoFar, Qual);3081if (!SoFar)3082return nullptr;3083}30843085Node *Base = getDerived().parseBaseUnresolvedName();3086if (Base == nullptr)3087return nullptr;3088return make<QualifiedName>(SoFar, Base);3089}30903091bool Global = consumeIf("gs");30923093// [gs] <base-unresolved-name> # x or (with "gs") ::x3094if (!consumeIf("sr")) {3095SoFar = getDerived().parseBaseUnresolvedName();3096if (SoFar == nullptr)3097return nullptr;3098if (Global)3099SoFar = make<GlobalQualifiedName>(SoFar);3100return SoFar;3101}31023103// [gs] sr <unresolved-qualifier-level>+ E <base-unresolved-name>3104if (std::isdigit(look())) {3105do {3106Node *Qual = getDerived().parseSimpleId();3107if (Qual == nullptr)3108return nullptr;3109if (SoFar)3110SoFar = make<QualifiedName>(SoFar, Qual);3111else if (Global)3112SoFar = make<GlobalQualifiedName>(Qual);3113else3114SoFar = Qual;3115if (!SoFar)3116return nullptr;3117} while (!consumeIf('E'));3118}3119// sr <unresolved-type> <base-unresolved-name>3120// sr <unresolved-type> <template-args> <base-unresolved-name>3121else {3122SoFar = getDerived().parseUnresolvedType();3123if (SoFar == nullptr)3124return nullptr;31253126if (look() == 'I') {3127Node *TA = getDerived().parseTemplateArgs();3128if (TA == nullptr)3129return nullptr;3130SoFar = make<NameWithTemplateArgs>(SoFar, TA);3131if (!SoFar)3132return nullptr;3133}3134}31353136assert(SoFar != nullptr);31373138Node *Base = getDerived().parseBaseUnresolvedName();3139if (Base == nullptr)3140return nullptr;3141return make<QualifiedName>(SoFar, Base);3142}31433144// <abi-tags> ::= <abi-tag> [<abi-tags>]3145// <abi-tag> ::= B <source-name>3146template <typename Derived, typename Alloc>3147Node *AbstractManglingParser<Derived, Alloc>::parseAbiTags(Node *N) {3148while (consumeIf('B')) {3149StringView SN = parseBareSourceName();3150if (SN.empty())3151return nullptr;3152N = make<AbiTagAttr>(N, SN);3153if (!N)3154return nullptr;3155}3156return N;3157}31583159// <number> ::= [n] <non-negative decimal integer>3160template <typename Alloc, typename Derived>3161StringView3162AbstractManglingParser<Alloc, Derived>::parseNumber(bool AllowNegative) {3163const char *Tmp = First;3164if (AllowNegative)3165consumeIf('n');3166if (numLeft() == 0 || !std::isdigit(*First))3167return StringView();3168while (numLeft() != 0 && std::isdigit(*First))3169++First;3170return StringView(Tmp, First);3171}31723173// <positive length number> ::= [0-9]*3174template <typename Alloc, typename Derived>3175bool AbstractManglingParser<Alloc, Derived>::parsePositiveInteger(size_t *Out) {3176*Out = 0;3177if (look() < '0' || look() > '9')3178return true;3179while (look() >= '0' && look() <= '9') {3180*Out *= 10;3181*Out += static_cast<size_t>(consume() - '0');3182}3183return false;3184}31853186template <typename Alloc, typename Derived>3187StringView AbstractManglingParser<Alloc, Derived>::parseBareSourceName() {3188size_t Int = 0;3189if (parsePositiveInteger(&Int) || numLeft() < Int)3190return StringView();3191StringView R(First, First + Int);3192First += Int;3193return R;3194}31953196// <function-type> ::= [<CV-qualifiers>] [<exception-spec>] [Dx] F [Y] <bare-function-type> [<ref-qualifier>] E3197//3198// <exception-spec> ::= Do # non-throwing exception-specification (e.g., noexcept, throw())3199// ::= DO <expression> E # computed (instantiation-dependent) noexcept3200// ::= Dw <type>+ E # dynamic exception specification with instantiation-dependent types3201//3202// <ref-qualifier> ::= R # & ref-qualifier3203// <ref-qualifier> ::= O # && ref-qualifier3204template <typename Derived, typename Alloc>3205Node *AbstractManglingParser<Derived, Alloc>::parseFunctionType() {3206Qualifiers CVQuals = parseCVQualifiers();32073208Node *ExceptionSpec = nullptr;3209if (consumeIf("Do")) {3210ExceptionSpec = make<NameType>("noexcept");3211if (!ExceptionSpec)3212return nullptr;3213} else if (consumeIf("DO")) {3214Node *E = getDerived().parseExpr();3215if (E == nullptr || !consumeIf('E'))3216return nullptr;3217ExceptionSpec = make<NoexceptSpec>(E);3218if (!ExceptionSpec)3219return nullptr;3220} else if (consumeIf("Dw")) {3221size_t SpecsBegin = Names.size();3222while (!consumeIf('E')) {3223Node *T = getDerived().parseType();3224if (T == nullptr)3225return nullptr;3226Names.push_back(T);3227}3228ExceptionSpec =3229make<DynamicExceptionSpec>(popTrailingNodeArray(SpecsBegin));3230if (!ExceptionSpec)3231return nullptr;3232}32333234consumeIf("Dx"); // transaction safe32353236if (!consumeIf('F'))3237return nullptr;3238consumeIf('Y'); // extern "C"3239Node *ReturnType = getDerived().parseType();3240if (ReturnType == nullptr)3241return nullptr;32423243FunctionRefQual ReferenceQualifier = FrefQualNone;3244size_t ParamsBegin = Names.size();3245while (true) {3246if (consumeIf('E'))3247break;3248if (consumeIf('v'))3249continue;3250if (consumeIf("RE")) {3251ReferenceQualifier = FrefQualLValue;3252break;3253}3254if (consumeIf("OE")) {3255ReferenceQualifier = FrefQualRValue;3256break;3257}3258Node *T = getDerived().parseType();3259if (T == nullptr)3260return nullptr;3261Names.push_back(T);3262}32633264NodeArray Params = popTrailingNodeArray(ParamsBegin);3265return make<FunctionType>(ReturnType, Params, CVQuals,3266ReferenceQualifier, ExceptionSpec);3267}32683269// extension:3270// <vector-type> ::= Dv <positive dimension number> _ <extended element type>3271// ::= Dv [<dimension expression>] _ <element type>3272// <extended element type> ::= <element type>3273// ::= p # AltiVec vector pixel3274template <typename Derived, typename Alloc>3275Node *AbstractManglingParser<Derived, Alloc>::parseVectorType() {3276if (!consumeIf("Dv"))3277return nullptr;3278if (look() >= '1' && look() <= '9') {3279StringView DimensionNumber = parseNumber();3280if (!consumeIf('_'))3281return nullptr;3282if (consumeIf('p'))3283return make<PixelVectorType>(DimensionNumber);3284Node *ElemType = getDerived().parseType();3285if (ElemType == nullptr)3286return nullptr;3287return make<VectorType>(ElemType, DimensionNumber);3288}32893290if (!consumeIf('_')) {3291Node *DimExpr = getDerived().parseExpr();3292if (!DimExpr)3293return nullptr;3294if (!consumeIf('_'))3295return nullptr;3296Node *ElemType = getDerived().parseType();3297if (!ElemType)3298return nullptr;3299return make<VectorType>(ElemType, DimExpr);3300}3301Node *ElemType = getDerived().parseType();3302if (!ElemType)3303return nullptr;3304return make<VectorType>(ElemType, StringView());3305}33063307// <decltype> ::= Dt <expression> E # decltype of an id-expression or class member access (C++0x)3308// ::= DT <expression> E # decltype of an expression (C++0x)3309template <typename Derived, typename Alloc>3310Node *AbstractManglingParser<Derived, Alloc>::parseDecltype() {3311if (!consumeIf('D'))3312return nullptr;3313if (!consumeIf('t') && !consumeIf('T'))3314return nullptr;3315Node *E = getDerived().parseExpr();3316if (E == nullptr)3317return nullptr;3318if (!consumeIf('E'))3319return nullptr;3320return make<EnclosingExpr>("decltype(", E, ")");3321}33223323// <array-type> ::= A <positive dimension number> _ <element type>3324// ::= A [<dimension expression>] _ <element type>3325template <typename Derived, typename Alloc>3326Node *AbstractManglingParser<Derived, Alloc>::parseArrayType() {3327if (!consumeIf('A'))3328return nullptr;33293330NodeOrString Dimension;33313332if (std::isdigit(look())) {3333Dimension = parseNumber();3334if (!consumeIf('_'))3335return nullptr;3336} else if (!consumeIf('_')) {3337Node *DimExpr = getDerived().parseExpr();3338if (DimExpr == nullptr)3339return nullptr;3340if (!consumeIf('_'))3341return nullptr;3342Dimension = DimExpr;3343}33443345Node *Ty = getDerived().parseType();3346if (Ty == nullptr)3347return nullptr;3348return make<ArrayType>(Ty, Dimension);3349}33503351// <pointer-to-member-type> ::= M <class type> <member type>3352template <typename Derived, typename Alloc>3353Node *AbstractManglingParser<Derived, Alloc>::parsePointerToMemberType() {3354if (!consumeIf('M'))3355return nullptr;3356Node *ClassType = getDerived().parseType();3357if (ClassType == nullptr)3358return nullptr;3359Node *MemberType = getDerived().parseType();3360if (MemberType == nullptr)3361return nullptr;3362return make<PointerToMemberType>(ClassType, MemberType);3363}33643365// <class-enum-type> ::= <name> # non-dependent type name, dependent type name, or dependent typename-specifier3366// ::= Ts <name> # dependent elaborated type specifier using 'struct' or 'class'3367// ::= Tu <name> # dependent elaborated type specifier using 'union'3368// ::= Te <name> # dependent elaborated type specifier using 'enum'3369template <typename Derived, typename Alloc>3370Node *AbstractManglingParser<Derived, Alloc>::parseClassEnumType() {3371StringView ElabSpef;3372if (consumeIf("Ts"))3373ElabSpef = "struct";3374else if (consumeIf("Tu"))3375ElabSpef = "union";3376else if (consumeIf("Te"))3377ElabSpef = "enum";33783379Node *Name = getDerived().parseName();3380if (Name == nullptr)3381return nullptr;33823383if (!ElabSpef.empty())3384return make<ElaboratedTypeSpefType>(ElabSpef, Name);33853386return Name;3387}33883389// <qualified-type> ::= <qualifiers> <type>3390// <qualifiers> ::= <extended-qualifier>* <CV-qualifiers>3391// <extended-qualifier> ::= U <source-name> [<template-args>] # vendor extended type qualifier3392template <typename Derived, typename Alloc>3393Node *AbstractManglingParser<Derived, Alloc>::parseQualifiedType() {3394if (consumeIf('U')) {3395StringView Qual = parseBareSourceName();3396if (Qual.empty())3397return nullptr;33983399// FIXME parse the optional <template-args> here!34003401// extension ::= U <objc-name> <objc-type> # objc-type<identifier>3402if (Qual.startsWith("objcproto")) {3403StringView ProtoSourceName = Qual.dropFront(std::strlen("objcproto"));3404StringView Proto;3405{3406SwapAndRestore<const char *> SaveFirst(First, ProtoSourceName.begin()),3407SaveLast(Last, ProtoSourceName.end());3408Proto = parseBareSourceName();3409}3410if (Proto.empty())3411return nullptr;3412Node *Child = getDerived().parseQualifiedType();3413if (Child == nullptr)3414return nullptr;3415return make<ObjCProtoName>(Child, Proto);3416}34173418Node *Child = getDerived().parseQualifiedType();3419if (Child == nullptr)3420return nullptr;3421return make<VendorExtQualType>(Child, Qual);3422}34233424Qualifiers Quals = parseCVQualifiers();3425Node *Ty = getDerived().parseType();3426if (Ty == nullptr)3427return nullptr;3428if (Quals != QualNone)3429Ty = make<QualType>(Ty, Quals);3430return Ty;3431}34323433// <type> ::= <builtin-type>3434// ::= <qualified-type>3435// ::= <function-type>3436// ::= <class-enum-type>3437// ::= <array-type>3438// ::= <pointer-to-member-type>3439// ::= <template-param>3440// ::= <template-template-param> <template-args>3441// ::= <decltype>3442// ::= P <type> # pointer3443// ::= R <type> # l-value reference3444// ::= O <type> # r-value reference (C++11)3445// ::= C <type> # complex pair (C99)3446// ::= G <type> # imaginary (C99)3447// ::= <substitution> # See Compression below3448// extension ::= U <objc-name> <objc-type> # objc-type<identifier>3449// extension ::= <vector-type> # <vector-type> starts with Dv3450//3451// <objc-name> ::= <k0 number> objcproto <k1 number> <identifier> # k0 = 9 + <number of digits in k1> + k13452// <objc-type> ::= <source-name> # PU<11+>objcproto 11objc_object<source-name> 11objc_object -> id<source-name>3453template <typename Derived, typename Alloc>3454Node *AbstractManglingParser<Derived, Alloc>::parseType() {3455Node *Result = nullptr;34563457switch (look()) {3458// ::= <qualified-type>3459case 'r':3460case 'V':3461case 'K': {3462unsigned AfterQuals = 0;3463if (look(AfterQuals) == 'r') ++AfterQuals;3464if (look(AfterQuals) == 'V') ++AfterQuals;3465if (look(AfterQuals) == 'K') ++AfterQuals;34663467if (look(AfterQuals) == 'F' ||3468(look(AfterQuals) == 'D' &&3469(look(AfterQuals + 1) == 'o' || look(AfterQuals + 1) == 'O' ||3470look(AfterQuals + 1) == 'w' || look(AfterQuals + 1) == 'x'))) {3471Result = getDerived().parseFunctionType();3472break;3473}3474_LIBCPP_FALLTHROUGH();3475}3476case 'U': {3477Result = getDerived().parseQualifiedType();3478break;3479}3480// <builtin-type> ::= v # void3481case 'v':3482++First;3483return make<NameType>("void");3484// ::= w # wchar_t3485case 'w':3486++First;3487return make<NameType>("wchar_t");3488// ::= b # bool3489case 'b':3490++First;3491return make<NameType>("bool");3492// ::= c # char3493case 'c':3494++First;3495return make<NameType>("char");3496// ::= a # signed char3497case 'a':3498++First;3499return make<NameType>("signed char");3500// ::= h # unsigned char3501case 'h':3502++First;3503return make<NameType>("unsigned char");3504// ::= s # short3505case 's':3506++First;3507return make<NameType>("short");3508// ::= t # unsigned short3509case 't':3510++First;3511return make<NameType>("unsigned short");3512// ::= i # int3513case 'i':3514++First;3515return make<NameType>("int");3516// ::= j # unsigned int3517case 'j':3518++First;3519return make<NameType>("unsigned int");3520// ::= l # long3521case 'l':3522++First;3523return make<NameType>("long");3524// ::= m # unsigned long3525case 'm':3526++First;3527return make<NameType>("unsigned long");3528// ::= x # long long, __int643529case 'x':3530++First;3531return make<NameType>("long long");3532// ::= y # unsigned long long, __int643533case 'y':3534++First;3535return make<NameType>("unsigned long long");3536// ::= n # __int1283537case 'n':3538++First;3539return make<NameType>("__int128");3540// ::= o # unsigned __int1283541case 'o':3542++First;3543return make<NameType>("unsigned __int128");3544// ::= f # float3545case 'f':3546++First;3547return make<NameType>("float");3548// ::= d # double3549case 'd':3550++First;3551return make<NameType>("double");3552// ::= e # long double, __float803553case 'e':3554++First;3555return make<NameType>("long double");3556// ::= g # __float1283557case 'g':3558++First;3559return make<NameType>("__float128");3560// ::= z # ellipsis3561case 'z':3562++First;3563return make<NameType>("...");35643565// <builtin-type> ::= u <source-name> # vendor extended type3566case 'u': {3567++First;3568StringView Res = parseBareSourceName();3569if (Res.empty())3570return nullptr;3571return make<NameType>(Res);3572}3573case 'D':3574switch (look(1)) {3575// ::= Dd # IEEE 754r decimal floating point (64 bits)3576case 'd':3577First += 2;3578return make<NameType>("decimal64");3579// ::= De # IEEE 754r decimal floating point (128 bits)3580case 'e':3581First += 2;3582return make<NameType>("decimal128");3583// ::= Df # IEEE 754r decimal floating point (32 bits)3584case 'f':3585First += 2;3586return make<NameType>("decimal32");3587// ::= Dh # IEEE 754r half-precision floating point (16 bits)3588case 'h':3589First += 2;3590return make<NameType>("decimal16");3591// ::= Di # char32_t3592case 'i':3593First += 2;3594return make<NameType>("char32_t");3595// ::= Ds # char16_t3596case 's':3597First += 2;3598return make<NameType>("char16_t");3599// ::= Da # auto (in dependent new-expressions)3600case 'a':3601First += 2;3602return make<NameType>("auto");3603// ::= Dc # decltype(auto)3604case 'c':3605First += 2;3606return make<NameType>("decltype(auto)");3607// ::= Dn # std::nullptr_t (i.e., decltype(nullptr))3608case 'n':3609First += 2;3610return make<NameType>("std::nullptr_t");36113612// ::= <decltype>3613case 't':3614case 'T': {3615Result = getDerived().parseDecltype();3616break;3617}3618// extension ::= <vector-type> # <vector-type> starts with Dv3619case 'v': {3620Result = getDerived().parseVectorType();3621break;3622}3623// ::= Dp <type> # pack expansion (C++0x)3624case 'p': {3625First += 2;3626Node *Child = getDerived().parseType();3627if (!Child)3628return nullptr;3629Result = make<ParameterPackExpansion>(Child);3630break;3631}3632// Exception specifier on a function type.3633case 'o':3634case 'O':3635case 'w':3636// Transaction safe function type.3637case 'x':3638Result = getDerived().parseFunctionType();3639break;3640}3641break;3642// ::= <function-type>3643case 'F': {3644Result = getDerived().parseFunctionType();3645break;3646}3647// ::= <array-type>3648case 'A': {3649Result = getDerived().parseArrayType();3650break;3651}3652// ::= <pointer-to-member-type>3653case 'M': {3654Result = getDerived().parsePointerToMemberType();3655break;3656}3657// ::= <template-param>3658case 'T': {3659// This could be an elaborate type specifier on a <class-enum-type>.3660if (look(1) == 's' || look(1) == 'u' || look(1) == 'e') {3661Result = getDerived().parseClassEnumType();3662break;3663}36643665Result = getDerived().parseTemplateParam();3666if (Result == nullptr)3667return nullptr;36683669// Result could be either of:3670// <type> ::= <template-param>3671// <type> ::= <template-template-param> <template-args>3672//3673// <template-template-param> ::= <template-param>3674// ::= <substitution>3675//3676// If this is followed by some <template-args>, and we're permitted to3677// parse them, take the second production.36783679if (TryToParseTemplateArgs && look() == 'I') {3680Node *TA = getDerived().parseTemplateArgs();3681if (TA == nullptr)3682return nullptr;3683Result = make<NameWithTemplateArgs>(Result, TA);3684}3685break;3686}3687// ::= P <type> # pointer3688case 'P': {3689++First;3690Node *Ptr = getDerived().parseType();3691if (Ptr == nullptr)3692return nullptr;3693Result = make<PointerType>(Ptr);3694break;3695}3696// ::= R <type> # l-value reference3697case 'R': {3698++First;3699Node *Ref = getDerived().parseType();3700if (Ref == nullptr)3701return nullptr;3702Result = make<ReferenceType>(Ref, ReferenceKind::LValue);3703break;3704}3705// ::= O <type> # r-value reference (C++11)3706case 'O': {3707++First;3708Node *Ref = getDerived().parseType();3709if (Ref == nullptr)3710return nullptr;3711Result = make<ReferenceType>(Ref, ReferenceKind::RValue);3712break;3713}3714// ::= C <type> # complex pair (C99)3715case 'C': {3716++First;3717Node *P = getDerived().parseType();3718if (P == nullptr)3719return nullptr;3720Result = make<PostfixQualifiedType>(P, " complex");3721break;3722}3723// ::= G <type> # imaginary (C99)3724case 'G': {3725++First;3726Node *P = getDerived().parseType();3727if (P == nullptr)3728return P;3729Result = make<PostfixQualifiedType>(P, " imaginary");3730break;3731}3732// ::= <substitution> # See Compression below3733case 'S': {3734if (look(1) && look(1) != 't') {3735Node *Sub = getDerived().parseSubstitution();3736if (Sub == nullptr)3737return nullptr;37383739// Sub could be either of:3740// <type> ::= <substitution>3741// <type> ::= <template-template-param> <template-args>3742//3743// <template-template-param> ::= <template-param>3744// ::= <substitution>3745//3746// If this is followed by some <template-args>, and we're permitted to3747// parse them, take the second production.37483749if (TryToParseTemplateArgs && look() == 'I') {3750Node *TA = getDerived().parseTemplateArgs();3751if (TA == nullptr)3752return nullptr;3753Result = make<NameWithTemplateArgs>(Sub, TA);3754break;3755}37563757// If all we parsed was a substitution, don't re-insert into the3758// substitution table.3759return Sub;3760}3761_LIBCPP_FALLTHROUGH();3762}3763// ::= <class-enum-type>3764default: {3765Result = getDerived().parseClassEnumType();3766break;3767}3768}37693770// If we parsed a type, insert it into the substitution table. Note that all3771// <builtin-type>s and <substitution>s have already bailed out, because they3772// don't get substitutions.3773if (Result != nullptr)3774Subs.push_back(Result);3775return Result;3776}37773778template <typename Derived, typename Alloc>3779Node *AbstractManglingParser<Derived, Alloc>::parsePrefixExpr(StringView Kind) {3780Node *E = getDerived().parseExpr();3781if (E == nullptr)3782return nullptr;3783return make<PrefixExpr>(Kind, E);3784}37853786template <typename Derived, typename Alloc>3787Node *AbstractManglingParser<Derived, Alloc>::parseBinaryExpr(StringView Kind) {3788Node *LHS = getDerived().parseExpr();3789if (LHS == nullptr)3790return nullptr;3791Node *RHS = getDerived().parseExpr();3792if (RHS == nullptr)3793return nullptr;3794return make<BinaryExpr>(LHS, Kind, RHS);3795}37963797template <typename Derived, typename Alloc>3798Node *3799AbstractManglingParser<Derived, Alloc>::parseIntegerLiteral(StringView Lit) {3800StringView Tmp = parseNumber(true);3801if (!Tmp.empty() && consumeIf('E'))3802return make<IntegerLiteral>(Lit, Tmp);3803return nullptr;3804}38053806// <CV-Qualifiers> ::= [r] [V] [K]3807template <typename Alloc, typename Derived>3808Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {3809Qualifiers CVR = QualNone;3810if (consumeIf('r'))3811CVR |= QualRestrict;3812if (consumeIf('V'))3813CVR |= QualVolatile;3814if (consumeIf('K'))3815CVR |= QualConst;3816return CVR;3817}38183819// <function-param> ::= fp <top-level CV-Qualifiers> _ # L == 0, first parameter3820// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters3821// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter3822// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters3823template <typename Derived, typename Alloc>3824Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {3825if (consumeIf("fp")) {3826parseCVQualifiers();3827StringView Num = parseNumber();3828if (!consumeIf('_'))3829return nullptr;3830return make<FunctionParam>(Num);3831}3832if (consumeIf("fL")) {3833if (parseNumber().empty())3834return nullptr;3835if (!consumeIf('p'))3836return nullptr;3837parseCVQualifiers();3838StringView Num = parseNumber();3839if (!consumeIf('_'))3840return nullptr;3841return make<FunctionParam>(Num);3842}3843return nullptr;3844}38453846// [gs] nw <expression>* _ <type> E # new (expr-list) type3847// [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)3848// [gs] na <expression>* _ <type> E # new[] (expr-list) type3849// [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)3850// <initializer> ::= pi <expression>* E # parenthesized initialization3851template <typename Derived, typename Alloc>3852Node *AbstractManglingParser<Derived, Alloc>::parseNewExpr() {3853bool Global = consumeIf("gs");3854bool IsArray = look(1) == 'a';3855if (!consumeIf("nw") && !consumeIf("na"))3856return nullptr;3857size_t Exprs = Names.size();3858while (!consumeIf('_')) {3859Node *Ex = getDerived().parseExpr();3860if (Ex == nullptr)3861return nullptr;3862Names.push_back(Ex);3863}3864NodeArray ExprList = popTrailingNodeArray(Exprs);3865Node *Ty = getDerived().parseType();3866if (Ty == nullptr)3867return Ty;3868if (consumeIf("pi")) {3869size_t InitsBegin = Names.size();3870while (!consumeIf('E')) {3871Node *Init = getDerived().parseExpr();3872if (Init == nullptr)3873return Init;3874Names.push_back(Init);3875}3876NodeArray Inits = popTrailingNodeArray(InitsBegin);3877return make<NewExpr>(ExprList, Ty, Inits, Global, IsArray);3878} else if (!consumeIf('E'))3879return nullptr;3880return make<NewExpr>(ExprList, Ty, NodeArray(), Global, IsArray);3881}38823883// cv <type> <expression> # conversion with one argument3884// cv <type> _ <expression>* E # conversion with a different number of arguments3885template <typename Derived, typename Alloc>3886Node *AbstractManglingParser<Derived, Alloc>::parseConversionExpr() {3887if (!consumeIf("cv"))3888return nullptr;3889Node *Ty;3890{3891SwapAndRestore<bool> SaveTemp(TryToParseTemplateArgs, false);3892Ty = getDerived().parseType();3893}38943895if (Ty == nullptr)3896return nullptr;38973898if (consumeIf('_')) {3899size_t ExprsBegin = Names.size();3900while (!consumeIf('E')) {3901Node *E = getDerived().parseExpr();3902if (E == nullptr)3903return E;3904Names.push_back(E);3905}3906NodeArray Exprs = popTrailingNodeArray(ExprsBegin);3907return make<ConversionExpr>(Ty, Exprs);3908}39093910Node *E[1] = {getDerived().parseExpr()};3911if (E[0] == nullptr)3912return nullptr;3913return make<ConversionExpr>(Ty, makeNodeArray(E, E + 1));3914}39153916// <expr-primary> ::= L <type> <value number> E # integer literal3917// ::= L <type> <value float> E # floating literal3918// ::= L <string type> E # string literal3919// ::= L <nullptr type> E # nullptr literal (i.e., "LDnE")3920// FIXME: ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C 2000)3921// ::= L <mangled-name> E # external name3922template <typename Derived, typename Alloc>3923Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {3924if (!consumeIf('L'))3925return nullptr;3926switch (look()) {3927case 'w':3928++First;3929return getDerived().parseIntegerLiteral("wchar_t");3930case 'b':3931if (consumeIf("b0E"))3932return make<BoolExpr>(0);3933if (consumeIf("b1E"))3934return make<BoolExpr>(1);3935return nullptr;3936case 'c':3937++First;3938return getDerived().parseIntegerLiteral("char");3939case 'a':3940++First;3941return getDerived().parseIntegerLiteral("signed char");3942case 'h':3943++First;3944return getDerived().parseIntegerLiteral("unsigned char");3945case 's':3946++First;3947return getDerived().parseIntegerLiteral("short");3948case 't':3949++First;3950return getDerived().parseIntegerLiteral("unsigned short");3951case 'i':3952++First;3953return getDerived().parseIntegerLiteral("");3954case 'j':3955++First;3956return getDerived().parseIntegerLiteral("u");3957case 'l':3958++First;3959return getDerived().parseIntegerLiteral("l");3960case 'm':3961++First;3962return getDerived().parseIntegerLiteral("ul");3963case 'x':3964++First;3965return getDerived().parseIntegerLiteral("ll");3966case 'y':3967++First;3968return getDerived().parseIntegerLiteral("ull");3969case 'n':3970++First;3971return getDerived().parseIntegerLiteral("__int128");3972case 'o':3973++First;3974return getDerived().parseIntegerLiteral("unsigned __int128");3975case 'f':3976++First;3977return getDerived().template parseFloatingLiteral<float>();3978case 'd':3979++First;3980return getDerived().template parseFloatingLiteral<double>();3981case 'e':3982++First;3983return getDerived().template parseFloatingLiteral<long double>();3984case '_':3985if (consumeIf("_Z")) {3986Node *R = getDerived().parseEncoding();3987if (R != nullptr && consumeIf('E'))3988return R;3989}3990return nullptr;3991case 'T':3992// Invalid mangled name per3993// http://sourcerytools.com/pipermail/cxx-abi-dev/2011-August/002422.html3994return nullptr;3995default: {3996// might be named type3997Node *T = getDerived().parseType();3998if (T == nullptr)3999return nullptr;4000StringView N = parseNumber();4001if (!N.empty()) {4002if (!consumeIf('E'))4003return nullptr;4004return make<IntegerCastExpr>(T, N);4005}4006if (consumeIf('E'))4007return T;4008return nullptr;4009}4010}4011}40124013// <braced-expression> ::= <expression>4014// ::= di <field source-name> <braced-expression> # .name = expr4015// ::= dx <index expression> <braced-expression> # [expr] = expr4016// ::= dX <range begin expression> <range end expression> <braced-expression>4017template <typename Derived, typename Alloc>4018Node *AbstractManglingParser<Derived, Alloc>::parseBracedExpr() {4019if (look() == 'd') {4020switch (look(1)) {4021case 'i': {4022First += 2;4023Node *Field = getDerived().parseSourceName(/*NameState=*/nullptr);4024if (Field == nullptr)4025return nullptr;4026Node *Init = getDerived().parseBracedExpr();4027if (Init == nullptr)4028return nullptr;4029return make<BracedExpr>(Field, Init, /*isArray=*/false);4030}4031case 'x': {4032First += 2;4033Node *Index = getDerived().parseExpr();4034if (Index == nullptr)4035return nullptr;4036Node *Init = getDerived().parseBracedExpr();4037if (Init == nullptr)4038return nullptr;4039return make<BracedExpr>(Index, Init, /*isArray=*/true);4040}4041case 'X': {4042First += 2;4043Node *RangeBegin = getDerived().parseExpr();4044if (RangeBegin == nullptr)4045return nullptr;4046Node *RangeEnd = getDerived().parseExpr();4047if (RangeEnd == nullptr)4048return nullptr;4049Node *Init = getDerived().parseBracedExpr();4050if (Init == nullptr)4051return nullptr;4052return make<BracedRangeExpr>(RangeBegin, RangeEnd, Init);4053}4054}4055}4056return getDerived().parseExpr();4057}40584059// (not yet in the spec)4060// <fold-expr> ::= fL <binary-operator-name> <expression> <expression>4061// ::= fR <binary-operator-name> <expression> <expression>4062// ::= fl <binary-operator-name> <expression>4063// ::= fr <binary-operator-name> <expression>4064template <typename Derived, typename Alloc>4065Node *AbstractManglingParser<Derived, Alloc>::parseFoldExpr() {4066if (!consumeIf('f'))4067return nullptr;40684069char FoldKind = look();4070bool IsLeftFold, HasInitializer;4071HasInitializer = FoldKind == 'L' || FoldKind == 'R';4072if (FoldKind == 'l' || FoldKind == 'L')4073IsLeftFold = true;4074else if (FoldKind == 'r' || FoldKind == 'R')4075IsLeftFold = false;4076else4077return nullptr;4078++First;40794080// FIXME: This map is duplicated in parseOperatorName and parseExpr.4081StringView OperatorName;4082if (consumeIf("aa")) OperatorName = "&&";4083else if (consumeIf("an")) OperatorName = "&";4084else if (consumeIf("aN")) OperatorName = "&=";4085else if (consumeIf("aS")) OperatorName = "=";4086else if (consumeIf("cm")) OperatorName = ",";4087else if (consumeIf("ds")) OperatorName = ".*";4088else if (consumeIf("dv")) OperatorName = "/";4089else if (consumeIf("dV")) OperatorName = "/=";4090else if (consumeIf("eo")) OperatorName = "^";4091else if (consumeIf("eO")) OperatorName = "^=";4092else if (consumeIf("eq")) OperatorName = "==";4093else if (consumeIf("ge")) OperatorName = ">=";4094else if (consumeIf("gt")) OperatorName = ">";4095else if (consumeIf("le")) OperatorName = "<=";4096else if (consumeIf("ls")) OperatorName = "<<";4097else if (consumeIf("lS")) OperatorName = "<<=";4098else if (consumeIf("lt")) OperatorName = "<";4099else if (consumeIf("mi")) OperatorName = "-";4100else if (consumeIf("mI")) OperatorName = "-=";4101else if (consumeIf("ml")) OperatorName = "*";4102else if (consumeIf("mL")) OperatorName = "*=";4103else if (consumeIf("ne")) OperatorName = "!=";4104else if (consumeIf("oo")) OperatorName = "||";4105else if (consumeIf("or")) OperatorName = "|";4106else if (consumeIf("oR")) OperatorName = "|=";4107else if (consumeIf("pl")) OperatorName = "+";4108else if (consumeIf("pL")) OperatorName = "+=";4109else if (consumeIf("rm")) OperatorName = "%";4110else if (consumeIf("rM")) OperatorName = "%=";4111else if (consumeIf("rs")) OperatorName = ">>";4112else if (consumeIf("rS")) OperatorName = ">>=";4113else return nullptr;41144115Node *Pack = getDerived().parseExpr(), *Init = nullptr;4116if (Pack == nullptr)4117return nullptr;4118if (HasInitializer) {4119Init = getDerived().parseExpr();4120if (Init == nullptr)4121return nullptr;4122}41234124if (IsLeftFold && Init)4125std::swap(Pack, Init);41264127return make<FoldExpr>(IsLeftFold, OperatorName, Pack, Init);4128}41294130// <expression> ::= <unary operator-name> <expression>4131// ::= <binary operator-name> <expression> <expression>4132// ::= <ternary operator-name> <expression> <expression> <expression>4133// ::= cl <expression>+ E # call4134// ::= cv <type> <expression> # conversion with one argument4135// ::= cv <type> _ <expression>* E # conversion with a different number of arguments4136// ::= [gs] nw <expression>* _ <type> E # new (expr-list) type4137// ::= [gs] nw <expression>* _ <type> <initializer> # new (expr-list) type (init)4138// ::= [gs] na <expression>* _ <type> E # new[] (expr-list) type4139// ::= [gs] na <expression>* _ <type> <initializer> # new[] (expr-list) type (init)4140// ::= [gs] dl <expression> # delete expression4141// ::= [gs] da <expression> # delete[] expression4142// ::= pp_ <expression> # prefix ++4143// ::= mm_ <expression> # prefix --4144// ::= ti <type> # typeid (type)4145// ::= te <expression> # typeid (expression)4146// ::= dc <type> <expression> # dynamic_cast<type> (expression)4147// ::= sc <type> <expression> # static_cast<type> (expression)4148// ::= cc <type> <expression> # const_cast<type> (expression)4149// ::= rc <type> <expression> # reinterpret_cast<type> (expression)4150// ::= st <type> # sizeof (a type)4151// ::= sz <expression> # sizeof (an expression)4152// ::= at <type> # alignof (a type)4153// ::= az <expression> # alignof (an expression)4154// ::= nx <expression> # noexcept (expression)4155// ::= <template-param>4156// ::= <function-param>4157// ::= dt <expression> <unresolved-name> # expr.name4158// ::= pt <expression> <unresolved-name> # expr->name4159// ::= ds <expression> <expression> # expr.*expr4160// ::= sZ <template-param> # size of a parameter pack4161// ::= sZ <function-param> # size of a function parameter pack4162// ::= sP <template-arg>* E # sizeof...(T), size of a captured template parameter pack from an alias template4163// ::= sp <expression> # pack expansion4164// ::= tw <expression> # throw expression4165// ::= tr # throw with no operand (rethrow)4166// ::= <unresolved-name> # f(p), N::f(p), ::f(p),4167// # freestanding dependent name (e.g., T::x),4168// # objectless nonstatic member reference4169// ::= fL <binary-operator-name> <expression> <expression>4170// ::= fR <binary-operator-name> <expression> <expression>4171// ::= fl <binary-operator-name> <expression>4172// ::= fr <binary-operator-name> <expression>4173// ::= <expr-primary>4174template <typename Derived, typename Alloc>4175Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {4176bool Global = consumeIf("gs");4177if (numLeft() < 2)4178return nullptr;41794180switch (*First) {4181case 'L':4182return getDerived().parseExprPrimary();4183case 'T':4184return getDerived().parseTemplateParam();4185case 'f': {4186// Disambiguate a fold expression from a <function-param>.4187if (look(1) == 'p' || (look(1) == 'L' && std::isdigit(look(2))))4188return getDerived().parseFunctionParam();4189return getDerived().parseFoldExpr();4190}4191case 'a':4192switch (First[1]) {4193case 'a':4194First += 2;4195return getDerived().parseBinaryExpr("&&");4196case 'd':4197First += 2;4198return getDerived().parsePrefixExpr("&");4199case 'n':4200First += 2;4201return getDerived().parseBinaryExpr("&");4202case 'N':4203First += 2;4204return getDerived().parseBinaryExpr("&=");4205case 'S':4206First += 2;4207return getDerived().parseBinaryExpr("=");4208case 't': {4209First += 2;4210Node *Ty = getDerived().parseType();4211if (Ty == nullptr)4212return nullptr;4213return make<EnclosingExpr>("alignof (", Ty, ")");4214}4215case 'z': {4216First += 2;4217Node *Ty = getDerived().parseExpr();4218if (Ty == nullptr)4219return nullptr;4220return make<EnclosingExpr>("alignof (", Ty, ")");4221}4222}4223return nullptr;4224case 'c':4225switch (First[1]) {4226// cc <type> <expression> # const_cast<type>(expression)4227case 'c': {4228First += 2;4229Node *Ty = getDerived().parseType();4230if (Ty == nullptr)4231return Ty;4232Node *Ex = getDerived().parseExpr();4233if (Ex == nullptr)4234return Ex;4235return make<CastExpr>("const_cast", Ty, Ex);4236}4237// cl <expression>+ E # call4238case 'l': {4239First += 2;4240Node *Callee = getDerived().parseExpr();4241if (Callee == nullptr)4242return Callee;4243size_t ExprsBegin = Names.size();4244while (!consumeIf('E')) {4245Node *E = getDerived().parseExpr();4246if (E == nullptr)4247return E;4248Names.push_back(E);4249}4250return make<CallExpr>(Callee, popTrailingNodeArray(ExprsBegin));4251}4252case 'm':4253First += 2;4254return getDerived().parseBinaryExpr(",");4255case 'o':4256First += 2;4257return getDerived().parsePrefixExpr("~");4258case 'v':4259return getDerived().parseConversionExpr();4260}4261return nullptr;4262case 'd':4263switch (First[1]) {4264case 'a': {4265First += 2;4266Node *Ex = getDerived().parseExpr();4267if (Ex == nullptr)4268return Ex;4269return make<DeleteExpr>(Ex, Global, /*is_array=*/true);4270}4271case 'c': {4272First += 2;4273Node *T = getDerived().parseType();4274if (T == nullptr)4275return T;4276Node *Ex = getDerived().parseExpr();4277if (Ex == nullptr)4278return Ex;4279return make<CastExpr>("dynamic_cast", T, Ex);4280}4281case 'e':4282First += 2;4283return getDerived().parsePrefixExpr("*");4284case 'l': {4285First += 2;4286Node *E = getDerived().parseExpr();4287if (E == nullptr)4288return E;4289return make<DeleteExpr>(E, Global, /*is_array=*/false);4290}4291case 'n':4292return getDerived().parseUnresolvedName();4293case 's': {4294First += 2;4295Node *LHS = getDerived().parseExpr();4296if (LHS == nullptr)4297return nullptr;4298Node *RHS = getDerived().parseExpr();4299if (RHS == nullptr)4300return nullptr;4301return make<MemberExpr>(LHS, ".*", RHS);4302}4303case 't': {4304First += 2;4305Node *LHS = getDerived().parseExpr();4306if (LHS == nullptr)4307return LHS;4308Node *RHS = getDerived().parseExpr();4309if (RHS == nullptr)4310return nullptr;4311return make<MemberExpr>(LHS, ".", RHS);4312}4313case 'v':4314First += 2;4315return getDerived().parseBinaryExpr("/");4316case 'V':4317First += 2;4318return getDerived().parseBinaryExpr("/=");4319}4320return nullptr;4321case 'e':4322switch (First[1]) {4323case 'o':4324First += 2;4325return getDerived().parseBinaryExpr("^");4326case 'O':4327First += 2;4328return getDerived().parseBinaryExpr("^=");4329case 'q':4330First += 2;4331return getDerived().parseBinaryExpr("==");4332}4333return nullptr;4334case 'g':4335switch (First[1]) {4336case 'e':4337First += 2;4338return getDerived().parseBinaryExpr(">=");4339case 't':4340First += 2;4341return getDerived().parseBinaryExpr(">");4342}4343return nullptr;4344case 'i':4345switch (First[1]) {4346case 'x': {4347First += 2;4348Node *Base = getDerived().parseExpr();4349if (Base == nullptr)4350return nullptr;4351Node *Index = getDerived().parseExpr();4352if (Index == nullptr)4353return Index;4354return make<ArraySubscriptExpr>(Base, Index);4355}4356case 'l': {4357First += 2;4358size_t InitsBegin = Names.size();4359while (!consumeIf('E')) {4360Node *E = getDerived().parseBracedExpr();4361if (E == nullptr)4362return nullptr;4363Names.push_back(E);4364}4365return make<InitListExpr>(nullptr, popTrailingNodeArray(InitsBegin));4366}4367}4368return nullptr;4369case 'l':4370switch (First[1]) {4371case 'e':4372First += 2;4373return getDerived().parseBinaryExpr("<=");4374case 's':4375First += 2;4376return getDerived().parseBinaryExpr("<<");4377case 'S':4378First += 2;4379return getDerived().parseBinaryExpr("<<=");4380case 't':4381First += 2;4382return getDerived().parseBinaryExpr("<");4383}4384return nullptr;4385case 'm':4386switch (First[1]) {4387case 'i':4388First += 2;4389return getDerived().parseBinaryExpr("-");4390case 'I':4391First += 2;4392return getDerived().parseBinaryExpr("-=");4393case 'l':4394First += 2;4395return getDerived().parseBinaryExpr("*");4396case 'L':4397First += 2;4398return getDerived().parseBinaryExpr("*=");4399case 'm':4400First += 2;4401if (consumeIf('_'))4402return getDerived().parsePrefixExpr("--");4403Node *Ex = getDerived().parseExpr();4404if (Ex == nullptr)4405return nullptr;4406return make<PostfixExpr>(Ex, "--");4407}4408return nullptr;4409case 'n':4410switch (First[1]) {4411case 'a':4412case 'w':4413return getDerived().parseNewExpr();4414case 'e':4415First += 2;4416return getDerived().parseBinaryExpr("!=");4417case 'g':4418First += 2;4419return getDerived().parsePrefixExpr("-");4420case 't':4421First += 2;4422return getDerived().parsePrefixExpr("!");4423case 'x':4424First += 2;4425Node *Ex = getDerived().parseExpr();4426if (Ex == nullptr)4427return Ex;4428return make<EnclosingExpr>("noexcept (", Ex, ")");4429}4430return nullptr;4431case 'o':4432switch (First[1]) {4433case 'n':4434return getDerived().parseUnresolvedName();4435case 'o':4436First += 2;4437return getDerived().parseBinaryExpr("||");4438case 'r':4439First += 2;4440return getDerived().parseBinaryExpr("|");4441case 'R':4442First += 2;4443return getDerived().parseBinaryExpr("|=");4444}4445return nullptr;4446case 'p':4447switch (First[1]) {4448case 'm':4449First += 2;4450return getDerived().parseBinaryExpr("->*");4451case 'l':4452First += 2;4453return getDerived().parseBinaryExpr("+");4454case 'L':4455First += 2;4456return getDerived().parseBinaryExpr("+=");4457case 'p': {4458First += 2;4459if (consumeIf('_'))4460return getDerived().parsePrefixExpr("++");4461Node *Ex = getDerived().parseExpr();4462if (Ex == nullptr)4463return Ex;4464return make<PostfixExpr>(Ex, "++");4465}4466case 's':4467First += 2;4468return getDerived().parsePrefixExpr("+");4469case 't': {4470First += 2;4471Node *L = getDerived().parseExpr();4472if (L == nullptr)4473return nullptr;4474Node *R = getDerived().parseExpr();4475if (R == nullptr)4476return nullptr;4477return make<MemberExpr>(L, "->", R);4478}4479}4480return nullptr;4481case 'q':4482if (First[1] == 'u') {4483First += 2;4484Node *Cond = getDerived().parseExpr();4485if (Cond == nullptr)4486return nullptr;4487Node *LHS = getDerived().parseExpr();4488if (LHS == nullptr)4489return nullptr;4490Node *RHS = getDerived().parseExpr();4491if (RHS == nullptr)4492return nullptr;4493return make<ConditionalExpr>(Cond, LHS, RHS);4494}4495return nullptr;4496case 'r':4497switch (First[1]) {4498case 'c': {4499First += 2;4500Node *T = getDerived().parseType();4501if (T == nullptr)4502return T;4503Node *Ex = getDerived().parseExpr();4504if (Ex == nullptr)4505return Ex;4506return make<CastExpr>("reinterpret_cast", T, Ex);4507}4508case 'm':4509First += 2;4510return getDerived().parseBinaryExpr("%");4511case 'M':4512First += 2;4513return getDerived().parseBinaryExpr("%=");4514case 's':4515First += 2;4516return getDerived().parseBinaryExpr(">>");4517case 'S':4518First += 2;4519return getDerived().parseBinaryExpr(">>=");4520}4521return nullptr;4522case 's':4523switch (First[1]) {4524case 'c': {4525First += 2;4526Node *T = getDerived().parseType();4527if (T == nullptr)4528return T;4529Node *Ex = getDerived().parseExpr();4530if (Ex == nullptr)4531return Ex;4532return make<CastExpr>("static_cast", T, Ex);4533}4534case 'p': {4535First += 2;4536Node *Child = getDerived().parseExpr();4537if (Child == nullptr)4538return nullptr;4539return make<ParameterPackExpansion>(Child);4540}4541case 'r':4542return getDerived().parseUnresolvedName();4543case 't': {4544First += 2;4545Node *Ty = getDerived().parseType();4546if (Ty == nullptr)4547return Ty;4548return make<EnclosingExpr>("sizeof (", Ty, ")");4549}4550case 'z': {4551First += 2;4552Node *Ex = getDerived().parseExpr();4553if (Ex == nullptr)4554return Ex;4555return make<EnclosingExpr>("sizeof (", Ex, ")");4556}4557case 'Z':4558First += 2;4559if (look() == 'T') {4560Node *R = getDerived().parseTemplateParam();4561if (R == nullptr)4562return nullptr;4563return make<SizeofParamPackExpr>(R);4564} else if (look() == 'f') {4565Node *FP = getDerived().parseFunctionParam();4566if (FP == nullptr)4567return nullptr;4568return make<EnclosingExpr>("sizeof... (", FP, ")");4569}4570return nullptr;4571case 'P': {4572First += 2;4573size_t ArgsBegin = Names.size();4574while (!consumeIf('E')) {4575Node *Arg = getDerived().parseTemplateArg();4576if (Arg == nullptr)4577return nullptr;4578Names.push_back(Arg);4579}4580auto *Pack = make<NodeArrayNode>(popTrailingNodeArray(ArgsBegin));4581if (!Pack)4582return nullptr;4583return make<EnclosingExpr>("sizeof... (", Pack, ")");4584}4585}4586return nullptr;4587case 't':4588switch (First[1]) {4589case 'e': {4590First += 2;4591Node *Ex = getDerived().parseExpr();4592if (Ex == nullptr)4593return Ex;4594return make<EnclosingExpr>("typeid (", Ex, ")");4595}4596case 'i': {4597First += 2;4598Node *Ty = getDerived().parseType();4599if (Ty == nullptr)4600return Ty;4601return make<EnclosingExpr>("typeid (", Ty, ")");4602}4603case 'l': {4604First += 2;4605Node *Ty = getDerived().parseType();4606if (Ty == nullptr)4607return nullptr;4608size_t InitsBegin = Names.size();4609while (!consumeIf('E')) {4610Node *E = getDerived().parseBracedExpr();4611if (E == nullptr)4612return nullptr;4613Names.push_back(E);4614}4615return make<InitListExpr>(Ty, popTrailingNodeArray(InitsBegin));4616}4617case 'r':4618First += 2;4619return make<NameType>("throw");4620case 'w': {4621First += 2;4622Node *Ex = getDerived().parseExpr();4623if (Ex == nullptr)4624return nullptr;4625return make<ThrowExpr>(Ex);4626}4627}4628return nullptr;4629case '1':4630case '2':4631case '3':4632case '4':4633case '5':4634case '6':4635case '7':4636case '8':4637case '9':4638return getDerived().parseUnresolvedName();4639}4640return nullptr;4641}46424643// <call-offset> ::= h <nv-offset> _4644// ::= v <v-offset> _4645//4646// <nv-offset> ::= <offset number>4647// # non-virtual base override4648//4649// <v-offset> ::= <offset number> _ <virtual offset number>4650// # virtual base override, with vcall offset4651template <typename Alloc, typename Derived>4652bool AbstractManglingParser<Alloc, Derived>::parseCallOffset() {4653// Just scan through the call offset, we never add this information into the4654// output.4655if (consumeIf('h'))4656return parseNumber(true).empty() || !consumeIf('_');4657if (consumeIf('v'))4658return parseNumber(true).empty() || !consumeIf('_') ||4659parseNumber(true).empty() || !consumeIf('_');4660return true;4661}46624663// <special-name> ::= TV <type> # virtual table4664// ::= TT <type> # VTT structure (construction vtable index)4665// ::= TI <type> # typeinfo structure4666// ::= TS <type> # typeinfo name (null-terminated byte string)4667// ::= Tc <call-offset> <call-offset> <base encoding>4668// # base is the nominal target function of thunk4669// # first call-offset is 'this' adjustment4670// # second call-offset is result adjustment4671// ::= T <call-offset> <base encoding>4672// # base is the nominal target function of thunk4673// ::= GV <object name> # Guard variable for one-time initialization4674// # No <type>4675// ::= TW <object name> # Thread-local wrapper4676// ::= TH <object name> # Thread-local initialization4677// ::= GR <object name> _ # First temporary4678// ::= GR <object name> <seq-id> _ # Subsequent temporaries4679// extension ::= TC <first type> <number> _ <second type> # construction vtable for second-in-first4680// extension ::= GR <object name> # reference temporary for object4681template <typename Derived, typename Alloc>4682Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {4683switch (look()) {4684case 'T':4685switch (look(1)) {4686// TV <type> # virtual table4687case 'V': {4688First += 2;4689Node *Ty = getDerived().parseType();4690if (Ty == nullptr)4691return nullptr;4692return make<SpecialName>("vtable for ", Ty);4693}4694// TT <type> # VTT structure (construction vtable index)4695case 'T': {4696First += 2;4697Node *Ty = getDerived().parseType();4698if (Ty == nullptr)4699return nullptr;4700return make<SpecialName>("VTT for ", Ty);4701}4702// TI <type> # typeinfo structure4703case 'I': {4704First += 2;4705Node *Ty = getDerived().parseType();4706if (Ty == nullptr)4707return nullptr;4708return make<SpecialName>("typeinfo for ", Ty);4709}4710// TS <type> # typeinfo name (null-terminated byte string)4711case 'S': {4712First += 2;4713Node *Ty = getDerived().parseType();4714if (Ty == nullptr)4715return nullptr;4716return make<SpecialName>("typeinfo name for ", Ty);4717}4718// Tc <call-offset> <call-offset> <base encoding>4719case 'c': {4720First += 2;4721if (parseCallOffset() || parseCallOffset())4722return nullptr;4723Node *Encoding = getDerived().parseEncoding();4724if (Encoding == nullptr)4725return nullptr;4726return make<SpecialName>("covariant return thunk to ", Encoding);4727}4728// extension ::= TC <first type> <number> _ <second type>4729// # construction vtable for second-in-first4730case 'C': {4731First += 2;4732Node *FirstType = getDerived().parseType();4733if (FirstType == nullptr)4734return nullptr;4735if (parseNumber(true).empty() || !consumeIf('_'))4736return nullptr;4737Node *SecondType = getDerived().parseType();4738if (SecondType == nullptr)4739return nullptr;4740return make<CtorVtableSpecialName>(SecondType, FirstType);4741}4742// TW <object name> # Thread-local wrapper4743case 'W': {4744First += 2;4745Node *Name = getDerived().parseName();4746if (Name == nullptr)4747return nullptr;4748return make<SpecialName>("thread-local wrapper routine for ", Name);4749}4750// TH <object name> # Thread-local initialization4751case 'H': {4752First += 2;4753Node *Name = getDerived().parseName();4754if (Name == nullptr)4755return nullptr;4756return make<SpecialName>("thread-local initialization routine for ", Name);4757}4758// T <call-offset> <base encoding>4759default: {4760++First;4761bool IsVirt = look() == 'v';4762if (parseCallOffset())4763return nullptr;4764Node *BaseEncoding = getDerived().parseEncoding();4765if (BaseEncoding == nullptr)4766return nullptr;4767if (IsVirt)4768return make<SpecialName>("virtual thunk to ", BaseEncoding);4769else4770return make<SpecialName>("non-virtual thunk to ", BaseEncoding);4771}4772}4773case 'G':4774switch (look(1)) {4775// GV <object name> # Guard variable for one-time initialization4776case 'V': {4777First += 2;4778Node *Name = getDerived().parseName();4779if (Name == nullptr)4780return nullptr;4781return make<SpecialName>("guard variable for ", Name);4782}4783// GR <object name> # reference temporary for object4784// GR <object name> _ # First temporary4785// GR <object name> <seq-id> _ # Subsequent temporaries4786case 'R': {4787First += 2;4788Node *Name = getDerived().parseName();4789if (Name == nullptr)4790return nullptr;4791size_t Count;4792bool ParsedSeqId = !parseSeqId(&Count);4793if (!consumeIf('_') && ParsedSeqId)4794return nullptr;4795return make<SpecialName>("reference temporary for ", Name);4796}4797}4798}4799return nullptr;4800}48014802// <encoding> ::= <function name> <bare-function-type>4803// ::= <data name>4804// ::= <special-name>4805template <typename Derived, typename Alloc>4806Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {4807if (look() == 'G' || look() == 'T')4808return getDerived().parseSpecialName();48094810auto IsEndOfEncoding = [&] {4811// The set of chars that can potentially follow an <encoding> (none of which4812// can start a <type>). Enumerating these allows us to avoid speculative4813// parsing.4814return numLeft() == 0 || look() == 'E' || look() == '.' || look() == '_';4815};48164817NameState NameInfo(this);4818Node *Name = getDerived().parseName(&NameInfo);4819if (Name == nullptr)4820return nullptr;48214822if (resolveForwardTemplateRefs(NameInfo))4823return nullptr;48244825if (IsEndOfEncoding())4826return Name;48274828Node *Attrs = nullptr;4829if (consumeIf("Ua9enable_ifI")) {4830size_t BeforeArgs = Names.size();4831while (!consumeIf('E')) {4832Node *Arg = getDerived().parseTemplateArg();4833if (Arg == nullptr)4834return nullptr;4835Names.push_back(Arg);4836}4837Attrs = make<EnableIfAttr>(popTrailingNodeArray(BeforeArgs));4838if (!Attrs)4839return nullptr;4840}48414842Node *ReturnType = nullptr;4843if (!NameInfo.CtorDtorConversion && NameInfo.EndsWithTemplateArgs) {4844ReturnType = getDerived().parseType();4845if (ReturnType == nullptr)4846return nullptr;4847}48484849if (consumeIf('v'))4850return make<FunctionEncoding>(ReturnType, Name, NodeArray(),4851Attrs, NameInfo.CVQualifiers,4852NameInfo.ReferenceQualifier);48534854size_t ParamsBegin = Names.size();4855do {4856Node *Ty = getDerived().parseType();4857if (Ty == nullptr)4858return nullptr;4859Names.push_back(Ty);4860} while (!IsEndOfEncoding());48614862return make<FunctionEncoding>(ReturnType, Name,4863popTrailingNodeArray(ParamsBegin),4864Attrs, NameInfo.CVQualifiers,4865NameInfo.ReferenceQualifier);4866}48674868template <class Float>4869struct FloatData;48704871template <>4872struct FloatData<float>4873{4874static const size_t mangled_size = 8;4875static const size_t max_demangled_size = 24;4876static constexpr const char* spec = "%af";4877};48784879template <>4880struct FloatData<double>4881{4882static const size_t mangled_size = 16;4883static const size_t max_demangled_size = 32;4884static constexpr const char* spec = "%a";4885};48864887template <>4888struct FloatData<long double>4889{4890#if defined(__mips__) && defined(__mips_n64) || defined(__aarch64__) || \4891defined(__wasm__)4892static const size_t mangled_size = 32;4893#elif defined(__arm__) || defined(__mips__) || defined(__hexagon__)4894static const size_t mangled_size = 16;4895#else4896static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms4897#endif4898static const size_t max_demangled_size = 40;4899static constexpr const char *spec = "%LaL";4900};49014902template <typename Alloc, typename Derived>4903template <class Float>4904Node *AbstractManglingParser<Alloc, Derived>::parseFloatingLiteral() {4905const size_t N = FloatData<Float>::mangled_size;4906if (numLeft() <= N)4907return nullptr;4908StringView Data(First, First + N);4909for (char C : Data)4910if (!std::isxdigit(C))4911return nullptr;4912First += N;4913if (!consumeIf('E'))4914return nullptr;4915return make<FloatLiteralImpl<Float>>(Data);4916}49174918// <seq-id> ::= <0-9A-Z>+4919template <typename Alloc, typename Derived>4920bool AbstractManglingParser<Alloc, Derived>::parseSeqId(size_t *Out) {4921if (!(look() >= '0' && look() <= '9') &&4922!(look() >= 'A' && look() <= 'Z'))4923return true;49244925size_t Id = 0;4926while (true) {4927if (look() >= '0' && look() <= '9') {4928Id *= 36;4929Id += static_cast<size_t>(look() - '0');4930} else if (look() >= 'A' && look() <= 'Z') {4931Id *= 36;4932Id += static_cast<size_t>(look() - 'A') + 10;4933} else {4934*Out = Id;4935return false;4936}4937++First;4938}4939}49404941// <substitution> ::= S <seq-id> _4942// ::= S_4943// <substitution> ::= Sa # ::std::allocator4944// <substitution> ::= Sb # ::std::basic_string4945// <substitution> ::= Ss # ::std::basic_string < char,4946// ::std::char_traits<char>,4947// ::std::allocator<char> >4948// <substitution> ::= Si # ::std::basic_istream<char, std::char_traits<char> >4949// <substitution> ::= So # ::std::basic_ostream<char, std::char_traits<char> >4950// <substitution> ::= Sd # ::std::basic_iostream<char, std::char_traits<char> >4951template <typename Derived, typename Alloc>4952Node *AbstractManglingParser<Derived, Alloc>::parseSubstitution() {4953if (!consumeIf('S'))4954return nullptr;49554956if (std::islower(look())) {4957Node *SpecialSub;4958switch (look()) {4959case 'a':4960++First;4961SpecialSub = make<SpecialSubstitution>(SpecialSubKind::allocator);4962break;4963case 'b':4964++First;4965SpecialSub = make<SpecialSubstitution>(SpecialSubKind::basic_string);4966break;4967case 's':4968++First;4969SpecialSub = make<SpecialSubstitution>(SpecialSubKind::string);4970break;4971case 'i':4972++First;4973SpecialSub = make<SpecialSubstitution>(SpecialSubKind::istream);4974break;4975case 'o':4976++First;4977SpecialSub = make<SpecialSubstitution>(SpecialSubKind::ostream);4978break;4979case 'd':4980++First;4981SpecialSub = make<SpecialSubstitution>(SpecialSubKind::iostream);4982break;4983default:4984return nullptr;4985}4986if (!SpecialSub)4987return nullptr;4988// Itanium C++ ABI 5.1.2: If a name that would use a built-in <substitution>4989// has ABI tags, the tags are appended to the substitution; the result is a4990// substitutable component.4991Node *WithTags = getDerived().parseAbiTags(SpecialSub);4992if (WithTags != SpecialSub) {4993Subs.push_back(WithTags);4994SpecialSub = WithTags;4995}4996return SpecialSub;4997}49984999// ::= S_5000if (consumeIf('_')) {5001if (Subs.empty())5002return nullptr;5003return Subs[0];5004}50055006// ::= S <seq-id> _5007size_t Index = 0;5008if (parseSeqId(&Index))5009return nullptr;5010++Index;5011if (!consumeIf('_') || Index >= Subs.size())5012return nullptr;5013return Subs[Index];5014}50155016// <template-param> ::= T_ # first template parameter5017// ::= T <parameter-2 non-negative number> _5018template <typename Derived, typename Alloc>5019Node *AbstractManglingParser<Derived, Alloc>::parseTemplateParam() {5020if (!consumeIf('T'))5021return nullptr;50225023size_t Index = 0;5024if (!consumeIf('_')) {5025if (parsePositiveInteger(&Index))5026return nullptr;5027++Index;5028if (!consumeIf('_'))5029return nullptr;5030}50315032// Itanium ABI 5.1.8: In a generic lambda, uses of auto in the parameter list5033// are mangled as the corresponding artificial template type parameter.5034if (ParsingLambdaParams)5035return make<NameType>("auto");50365037// If we're in a context where this <template-param> refers to a5038// <template-arg> further ahead in the mangled name (currently just conversion5039// operator types), then we should only look it up in the right context.5040if (PermitForwardTemplateReferences) {5041Node *ForwardRef = make<ForwardTemplateReference>(Index);5042if (!ForwardRef)5043return nullptr;5044assert(ForwardRef->getKind() == Node::KForwardTemplateReference);5045ForwardTemplateRefs.push_back(5046static_cast<ForwardTemplateReference *>(ForwardRef));5047return ForwardRef;5048}50495050if (Index >= TemplateParams.size())5051return nullptr;5052return TemplateParams[Index];5053}50545055// <template-arg> ::= <type> # type or template5056// ::= X <expression> E # expression5057// ::= <expr-primary> # simple expressions5058// ::= J <template-arg>* E # argument pack5059// ::= LZ <encoding> E # extension5060template <typename Derived, typename Alloc>5061Node *AbstractManglingParser<Derived, Alloc>::parseTemplateArg() {5062switch (look()) {5063case 'X': {5064++First;5065Node *Arg = getDerived().parseExpr();5066if (Arg == nullptr || !consumeIf('E'))5067return nullptr;5068return Arg;5069}5070case 'J': {5071++First;5072size_t ArgsBegin = Names.size();5073while (!consumeIf('E')) {5074Node *Arg = getDerived().parseTemplateArg();5075if (Arg == nullptr)5076return nullptr;5077Names.push_back(Arg);5078}5079NodeArray Args = popTrailingNodeArray(ArgsBegin);5080return make<TemplateArgumentPack>(Args);5081}5082case 'L': {5083// ::= LZ <encoding> E # extension5084if (look(1) == 'Z') {5085First += 2;5086Node *Arg = getDerived().parseEncoding();5087if (Arg == nullptr || !consumeIf('E'))5088return nullptr;5089return Arg;5090}5091// ::= <expr-primary> # simple expressions5092return getDerived().parseExprPrimary();5093}5094default:5095return getDerived().parseType();5096}5097}50985099// <template-args> ::= I <template-arg>* E5100// extension, the abi says <template-arg>+5101template <typename Derived, typename Alloc>5102Node *5103AbstractManglingParser<Derived, Alloc>::parseTemplateArgs(bool TagTemplates) {5104if (!consumeIf('I'))5105return nullptr;51065107// <template-params> refer to the innermost <template-args>. Clear out any5108// outer args that we may have inserted into TemplateParams.5109if (TagTemplates)5110TemplateParams.clear();51115112size_t ArgsBegin = Names.size();5113while (!consumeIf('E')) {5114if (TagTemplates) {5115auto OldParams = std::move(TemplateParams);5116Node *Arg = getDerived().parseTemplateArg();5117TemplateParams = std::move(OldParams);5118if (Arg == nullptr)5119return nullptr;5120Names.push_back(Arg);5121Node *TableEntry = Arg;5122if (Arg->getKind() == Node::KTemplateArgumentPack) {5123TableEntry = make<ParameterPack>(5124static_cast<TemplateArgumentPack*>(TableEntry)->getElements());5125if (!TableEntry)5126return nullptr;5127}5128TemplateParams.push_back(TableEntry);5129} else {5130Node *Arg = getDerived().parseTemplateArg();5131if (Arg == nullptr)5132return nullptr;5133Names.push_back(Arg);5134}5135}5136return make<TemplateArgs>(popTrailingNodeArray(ArgsBegin));5137}51385139// <mangled-name> ::= _Z <encoding>5140// ::= <type>5141// extension ::= ___Z <encoding> _block_invoke5142// extension ::= ___Z <encoding> _block_invoke<decimal-digit>+5143// extension ::= ___Z <encoding> _block_invoke_<decimal-digit>+5144template <typename Derived, typename Alloc>5145Node *AbstractManglingParser<Derived, Alloc>::parse() {5146if (consumeIf("_Z")) {5147Node *Encoding = getDerived().parseEncoding();5148if (Encoding == nullptr)5149return nullptr;5150if (look() == '.') {5151Encoding = make<DotSuffix>(Encoding, StringView(First, Last));5152First = Last;5153}5154if (numLeft() != 0)5155return nullptr;5156return Encoding;5157}51585159if (consumeIf("___Z")) {5160Node *Encoding = getDerived().parseEncoding();5161if (Encoding == nullptr || !consumeIf("_block_invoke"))5162return nullptr;5163bool RequireNumber = consumeIf('_');5164if (parseNumber().empty() && RequireNumber)5165return nullptr;5166if (look() == '.')5167First = Last;5168if (numLeft() != 0)5169return nullptr;5170return make<SpecialName>("invocation function for block in ", Encoding);5171}51725173Node *Ty = getDerived().parseType();5174if (numLeft() != 0)5175return nullptr;5176return Ty;5177}51785179template <typename Alloc>5180struct ManglingParser : AbstractManglingParser<ManglingParser<Alloc>, Alloc> {5181using AbstractManglingParser<ManglingParser<Alloc>,5182Alloc>::AbstractManglingParser;5183};51845185} // namespace itanium_demangle5186} // namespace51875188#endif // LIBCXX_DEMANGLE_ITANIUMDEMANGLE_H518951905191