Index: include/llvm/Demangle/ItaniumDemangle.h =================================================================== --- include/llvm/Demangle/ItaniumDemangle.h +++ include/llvm/Demangle/ItaniumDemangle.h @@ -1,4 +1,4 @@ -//===------------------------- ItaniumDemangle.cpp ------------------------===// +//===------------------------- ItaniumDemangle.h ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,14 +7,16 @@ // //===----------------------------------------------------------------------===// +#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_H +#define LLVM_DEMANGLE_ITANIUMDEMANGLE_H + // FIXME: (possibly) incomplete list of features that clang mangles that this // file does not yet support: // - C++ modules TS -#include "Compiler.h" -#include "StringView.h" -#include "Utility.h" -#include "llvm/Demangle/Demangle.h" +#include "llvm/Demangle/Compiler.h" +#include "llvm/Demangle/StringView.h" +#include "llvm/Demangle/Utility.h" #include #include @@ -23,66 +25,97 @@ #include #include #include -#include -namespace { +#define FOR_EACH_NODE_KIND(X) \ + X(NodeArrayNode) \ + X(DotSuffix) \ + X(VendorExtQualType) \ + X(QualType) \ + X(ConversionOperatorType) \ + X(PostfixQualifiedType) \ + X(ElaboratedTypeSpefType) \ + X(NameType) \ + X(AbiTagAttr) \ + X(EnableIfAttr) \ + X(ObjCProtoName) \ + X(PointerType) \ + X(ReferenceType) \ + X(PointerToMemberType) \ + X(ArrayType) \ + X(FunctionType) \ + X(NoexceptSpec) \ + X(DynamicExceptionSpec) \ + X(FunctionEncoding) \ + X(LiteralOperator) \ + X(SpecialName) \ + X(CtorVtableSpecialName) \ + X(QualifiedName) \ + X(NestedName) \ + X(LocalName) \ + X(VectorType) \ + X(PixelVectorType) \ + X(ParameterPack) \ + X(TemplateArgumentPack) \ + X(ParameterPackExpansion) \ + X(TemplateArgs) \ + X(ForwardTemplateReference) \ + X(NameWithTemplateArgs) \ + X(GlobalQualifiedName) \ + X(StdQualifiedName) \ + X(ExpandedSpecialSubstitution) \ + X(SpecialSubstitution) \ + X(CtorDtorName) \ + X(DtorName) \ + X(UnnamedTypeName) \ + X(ClosureTypeName) \ + X(StructuredBindingName) \ + X(BinaryExpr) \ + X(ArraySubscriptExpr) \ + X(PostfixExpr) \ + X(ConditionalExpr) \ + X(MemberExpr) \ + X(EnclosingExpr) \ + X(CastExpr) \ + X(SizeofParamPackExpr) \ + X(CallExpr) \ + X(NewExpr) \ + X(DeleteExpr) \ + X(PrefixExpr) \ + X(FunctionParam) \ + X(ConversionExpr) \ + X(InitListExpr) \ + X(FoldExpr) \ + X(ThrowExpr) \ + X(BoolExpr) \ + X(IntegerCastExpr) \ + X(IntegerLiteral) \ + X(FloatLiteral) \ + X(DoubleLiteral) \ + X(LongDoubleLiteral) \ + X(BracedExpr) \ + X(BracedRangeExpr) + +namespace llvm { +namespace itanium_demangle { // Base class of all AST nodes. The AST is built by the parser, then is // traversed by the printLeft/Right functions to produce a demangled string. class Node { public: enum Kind : unsigned char { - KNodeArrayNode, - KDotSuffix, - KVendorExtQualType, - KQualType, - KConversionOperatorType, - KPostfixQualifiedType, - KElaboratedTypeSpefType, - KNameType, - KAbiTagAttr, - KEnableIfAttr, - KObjCProtoName, - KPointerType, - KReferenceType, - KPointerToMemberType, - KArrayType, - KFunctionType, - KNoexceptSpec, - KDynamicExceptionSpec, - KFunctionEncoding, - KLiteralOperator, - KSpecialName, - KCtorVtableSpecialName, - KQualifiedName, - KNestedName, - KLocalName, - KVectorType, - KParameterPack, - KTemplateArgumentPack, - KParameterPackExpansion, - KTemplateArgs, - KForwardTemplateReference, - KNameWithTemplateArgs, - KGlobalQualifiedName, - KStdQualifiedName, - KExpandedSpecialSubstitution, - KSpecialSubstitution, - KCtorDtorName, - KDtorName, - KUnnamedTypeName, - KClosureTypeName, - KStructuredBindingName, - KExpr, - KBracedExpr, - KBracedRangeExpr, +#define ENUMERATOR(NodeKind) K ## NodeKind, + FOR_EACH_NODE_KIND(ENUMERATOR) +#undef ENUMERATOR }; - Kind K; - /// Three-way bool to track a cached value. Unknown is possible if this node /// has an unexpanded parameter pack below it that may affect this cache. enum class Cache : unsigned char { Yes, No, Unknown, }; +private: + Kind K; + + // FIXME: Make these protected. +public: /// Tracks if this node has a component on its right side, in which case we /// need to call printRight. Cache RHSComponentCache; @@ -95,11 +128,21 @@ /// affect how we format the output string. Cache FunctionCache; +public: Node(Kind K_, Cache RHSComponentCache_ = Cache::No, Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No) : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_), FunctionCache(FunctionCache_) {} + /// Visit the most-derived object corresponding to this object. + template void visit(Fn F) const; + + // The following function is provided by all derived classes: + // + // Call F with arguments that, when passed to the constructor of this node, + // would construct an equivalent node. + //template void match(Fn F) const; + bool hasRHSComponent(OutputStream &S) const { if (RHSComponentCache != Cache::Unknown) return RHSComponentCache == Cache::Yes; @@ -151,14 +194,7 @@ virtual ~Node() = default; #ifndef NDEBUG - LLVM_DUMP_METHOD void dump() const { - char *Buffer = static_cast(std::malloc(1024)); - OutputStream S(Buffer, 1024); - print(S); - S += '\0'; - printf("Symbol dump for %p: %s\n", (const void*)this, S.getBuffer()); - std::free(S.getBuffer()); - } + LLVM_DUMP_METHOD void dump() const; #endif }; @@ -203,6 +239,9 @@ struct NodeArrayNode : Node { NodeArray Array; NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {} + + template void match(Fn F) const { F(Array); } + void printLeft(OutputStream &S) const override { Array.printWithComma(S); } @@ -213,9 +252,11 @@ const StringView Suffix; public: - DotSuffix(Node *Prefix_, StringView Suffix_) + DotSuffix(const Node *Prefix_, StringView Suffix_) : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} + template void match(Fn F) const { F(Prefix, Suffix); } + void printLeft(OutputStream &s) const override { Prefix->print(s); s += " ("; @@ -229,9 +270,11 @@ StringView Ext; public: - VendorExtQualType(Node *Ty_, StringView Ext_) + VendorExtQualType(const Node *Ty_, StringView Ext_) : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} + template void match(Fn F) const { F(Ty, Ext); } + void printLeft(OutputStream &S) const override { Ty->print(S); S += " "; @@ -252,8 +295,8 @@ QualRestrict = 0x4, }; -void addQualifiers(Qualifiers &Q1, Qualifiers Q2) { - Q1 = static_cast(Q1 | Q2); +inline Qualifiers operator|=(Qualifiers &Q1, Qualifiers Q2) { + return Q1 = static_cast(Q1 | Q2); } class QualType : public Node { @@ -271,11 +314,13 @@ } public: - QualType(Node *Child_, Qualifiers Quals_) + QualType(const Node *Child_, Qualifiers Quals_) : Node(KQualType, Child_->RHSComponentCache, Child_->ArrayCache, Child_->FunctionCache), Quals(Quals_), Child(Child_) {} + template void match(Fn F) const { F(Child, Quals); } + bool hasRHSComponentSlow(OutputStream &S) const override { return Child->hasRHSComponent(S); } @@ -298,9 +343,11 @@ const Node *Ty; public: - ConversionOperatorType(Node *Ty_) + ConversionOperatorType(const Node *Ty_) : Node(KConversionOperatorType), Ty(Ty_) {} + template void match(Fn F) const { F(Ty); } + void printLeft(OutputStream &S) const override { S += "operator "; Ty->print(S); @@ -315,6 +362,8 @@ PostfixQualifiedType(Node *Ty_, StringView Postfix_) : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} + template void match(Fn F) const { F(Ty, Postfix); } + void printLeft(OutputStream &s) const override { Ty->printLeft(s); s += Postfix; @@ -327,6 +376,8 @@ public: NameType(StringView Name_) : Node(KNameType), Name(Name_) {} + template void match(Fn F) const { F(Name); } + StringView getName() const { return Name; } StringView getBaseName() const override { return Name; } @@ -340,6 +391,8 @@ ElaboratedTypeSpefType(StringView Kind_, Node *Child_) : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} + template void match(Fn F) const { F(Kind, Child); } + void printLeft(OutputStream &S) const override { S += Kind; S += ' '; @@ -356,6 +409,8 @@ Base_->ArrayCache, Base_->FunctionCache), Base(Base_), Tag(Tag_) {} + template void match(Fn F) const { F(Base, Tag); } + void printLeft(OutputStream &S) const override { Base->printLeft(S); S += "[abi:"; @@ -370,6 +425,8 @@ EnableIfAttr(NodeArray Conditions_) : Node(KEnableIfAttr), Conditions(Conditions_) {} + template void match(Fn F) const { F(Conditions); } + void printLeft(OutputStream &S) const override { S += " [enable_if:"; Conditions.printWithComma(S); @@ -378,18 +435,20 @@ }; class ObjCProtoName : public Node { - Node *Ty; + const Node *Ty; StringView Protocol; friend class PointerType; public: - ObjCProtoName(Node *Ty_, StringView Protocol_) + ObjCProtoName(const Node *Ty_, StringView Protocol_) : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} + template void match(Fn F) const { F(Ty, Protocol); } + bool isObjCObject() const { return Ty->getKind() == KNameType && - static_cast(Ty)->getName() == "objc_object"; + static_cast(Ty)->getName() == "objc_object"; } void printLeft(OutputStream &S) const override { @@ -404,10 +463,12 @@ const Node *Pointee; public: - PointerType(Node *Pointee_) + PointerType(const Node *Pointee_) : Node(KPointerType, Pointee_->RHSComponentCache), Pointee(Pointee_) {} + template void match(Fn F) const { F(Pointee); } + bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } @@ -469,10 +530,12 @@ } public: - ReferenceType(Node *Pointee_, ReferenceKind RK_) + ReferenceType(const Node *Pointee_, ReferenceKind RK_) : Node(KReferenceType, Pointee_->RHSComponentCache), Pointee(Pointee_), RK(RK_) {} + template void match(Fn F) const { F(Pointee, RK); } + bool hasRHSComponentSlow(OutputStream &S) const override { return Pointee->hasRHSComponent(S); } @@ -506,10 +569,12 @@ const Node *MemberType; public: - PointerToMemberType(Node *ClassType_, Node *MemberType_) + PointerToMemberType(const Node *ClassType_, const Node *MemberType_) : Node(KPointerToMemberType, MemberType_->RHSComponentCache), ClassType(ClassType_), MemberType(MemberType_) {} + template void match(Fn F) const { F(ClassType, MemberType); } + bool hasRHSComponentSlow(OutputStream &S) const override { return MemberType->hasRHSComponent(S); } @@ -568,22 +633,17 @@ }; class ArrayType final : public Node { - Node *Base; + const Node *Base; NodeOrString Dimension; public: - ArrayType(Node *Base_, NodeOrString Dimension_) + ArrayType(const Node *Base_, NodeOrString Dimension_ = NodeOrString()) : Node(KArrayType, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::Yes), Base(Base_), Dimension(Dimension_) {} - // Incomplete array type. - ArrayType(Node *Base_) - : Node(KArrayType, - /*RHSComponentCache=*/Cache::Yes, - /*ArrayCache=*/Cache::Yes), - Base(Base_) {} + template void match(Fn F) const { F(Base, Dimension); } bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasArraySlow(OutputStream &) const override { return true; } @@ -604,21 +664,25 @@ }; class FunctionType final : public Node { - Node *Ret; + const Node *Ret; NodeArray Params; Qualifiers CVQuals; FunctionRefQual RefQual; - Node *ExceptionSpec; + const Node *ExceptionSpec; public: - FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, - FunctionRefQual RefQual_, Node *ExceptionSpec_) + FunctionType(const Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, + FunctionRefQual RefQual_, const Node *ExceptionSpec_) : Node(KFunctionType, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, /*FunctionCache=*/Cache::Yes), Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_), ExceptionSpec(ExceptionSpec_) {} + template void match(Fn F) const { + F(Ret, Params, CVQuals, RefQual, ExceptionSpec); + } + bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasFunctionSlow(OutputStream &) const override { return true; } @@ -660,9 +724,11 @@ }; class NoexceptSpec : public Node { - Node *E; + const Node *E; public: - NoexceptSpec(Node *E_) : Node(KNoexceptSpec), E(E_) {} + NoexceptSpec(const Node *E_) : Node(KNoexceptSpec), E(E_) {} + + template void match(Fn F) const { F(E); } void printLeft(OutputStream &S) const override { S += "noexcept("; @@ -677,6 +743,8 @@ DynamicExceptionSpec(NodeArray Types_) : Node(KDynamicExceptionSpec), Types(Types_) {} + template void match(Fn F) const { F(Types); } + void printLeft(OutputStream &S) const override { S += "throw("; Types.printWithComma(S); @@ -685,31 +753,36 @@ }; class FunctionEncoding final : public Node { - Node *Ret; - Node *Name; + const Node *Ret; + const Node *Name; NodeArray Params; - Node *Attrs; + const Node *Attrs; Qualifiers CVQuals; FunctionRefQual RefQual; public: - FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_, - Node *Attrs_, Qualifiers CVQuals_, FunctionRefQual RefQual_) + FunctionEncoding(const Node *Ret_, const Node *Name_, NodeArray Params_, + const Node *Attrs_, Qualifiers CVQuals_, + FunctionRefQual RefQual_) : Node(KFunctionEncoding, /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, /*FunctionCache=*/Cache::Yes), Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_), CVQuals(CVQuals_), RefQual(RefQual_) {} + template void match(Fn F) const { + F(Ret, Name, Params, Attrs, CVQuals, RefQual); + } + Qualifiers getCVQuals() const { return CVQuals; } FunctionRefQual getRefQual() const { return RefQual; } NodeArray getParams() const { return Params; } - Node *getReturnType() const { return Ret; } + const Node *getReturnType() const { return Ret; } bool hasRHSComponentSlow(OutputStream &) const override { return true; } bool hasFunctionSlow(OutputStream &) const override { return true; } - Node *getName() { return const_cast(Name); } + const Node *getName() const { return Name; } void printLeft(OutputStream &S) const override { if (Ret) { @@ -748,7 +821,10 @@ const Node *OpName; public: - LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {} + LiteralOperator(const Node *OpName_) + : Node(KLiteralOperator), OpName(OpName_) {} + + template void match(Fn F) const { F(OpName); } void printLeft(OutputStream &S) const override { S += "operator\"\" "; @@ -761,9 +837,11 @@ const Node *Child; public: - SpecialName(StringView Special_, Node* Child_) + SpecialName(StringView Special_, const Node *Child_) : Node(KSpecialName), Special(Special_), Child(Child_) {} + template void match(Fn F) const { F(Special, Child); } + void printLeft(OutputStream &S) const override { S += Special; Child->print(S); @@ -775,10 +853,12 @@ const Node *SecondType; public: - CtorVtableSpecialName(Node *FirstType_, Node *SecondType_) + CtorVtableSpecialName(const Node *FirstType_, const Node *SecondType_) : Node(KCtorVtableSpecialName), FirstType(FirstType_), SecondType(SecondType_) {} + template void match(Fn F) const { F(FirstType, SecondType); } + void printLeft(OutputStream &S) const override { S += "construction vtable for "; FirstType->print(S); @@ -794,6 +874,8 @@ NestedName(Node *Qual_, Node *Name_) : Node(KNestedName), Qual(Qual_), Name(Name_) {} + template void match(Fn F) const { F(Qual, Name); } + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -810,6 +892,8 @@ LocalName(Node *Encoding_, Node *Entity_) : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} + template void match(Fn F) const { F(Encoding, Entity); } + void printLeft(OutputStream &S) const override { Encoding->print(S); S += "::"; @@ -823,9 +907,11 @@ const Node *Name; public: - QualifiedName(Node* Qualifier_, Node* Name_) + QualifiedName(const Node *Qualifier_, const Node *Name_) : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {} + template void match(Fn F) const { F(Qualifier, Name); } + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -838,30 +924,39 @@ class VectorType final : public Node { const Node *BaseType; const NodeOrString Dimension; - const bool IsPixel; public: - VectorType(NodeOrString Dimension_) - : Node(KVectorType), BaseType(nullptr), Dimension(Dimension_), - IsPixel(true) {} - VectorType(Node *BaseType_, NodeOrString Dimension_) + VectorType(const Node *BaseType_, NodeOrString Dimension_) : Node(KVectorType), BaseType(BaseType_), - Dimension(Dimension_), IsPixel(false) {} + Dimension(Dimension_) {} + + template void match(Fn F) const { F(BaseType, Dimension); } void printLeft(OutputStream &S) const override { - if (IsPixel) { - S += "pixel vector["; + BaseType->print(S); + S += " vector["; + if (Dimension.isNode()) + Dimension.asNode()->print(S); + else if (Dimension.isString()) S += Dimension.asString(); - S += "]"; - } else { - BaseType->print(S); - S += " vector["; - if (Dimension.isNode()) - Dimension.asNode()->print(S); - else if (Dimension.isString()) - S += Dimension.asString(); - S += "]"; - } + S += "]"; + } +}; + +class PixelVectorType final : public Node { + const NodeOrString Dimension; + +public: + PixelVectorType(NodeOrString Dimension_) + : Node(KPixelVectorType), Dimension(Dimension_) {} + + template void match(Fn F) const { F(Dimension); } + + void printLeft(OutputStream &S) const override { + // FIXME: This should demangle as "vector pixel". + S += "pixel vector["; + S += Dimension.asString(); + S += "]"; } }; @@ -901,6 +996,8 @@ RHSComponentCache = Cache::No; } + template void match(Fn F) const { F(Data); } + bool hasRHSComponentSlow(OutputStream &S) const override { initializePackExpansion(S); size_t Idx = S.CurrentPackIndex; @@ -947,6 +1044,8 @@ TemplateArgumentPack(NodeArray Elements_) : Node(KTemplateArgumentPack), Elements(Elements_) {} + template void match(Fn F) const { F(Elements); } + NodeArray getElements() const { return Elements; } void printLeft(OutputStream &S) const override { @@ -960,9 +1059,11 @@ const Node *Child; public: - ParameterPackExpansion(Node* Child_) + ParameterPackExpansion(const Node *Child_) : Node(KParameterPackExpansion), Child(Child_) {} + template void match(Fn F) const { F(Child); } + const Node *getChild() const { return Child; } void printLeft(OutputStream &S) const override { @@ -1004,6 +1105,8 @@ public: TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} + template void match(Fn F) const { F(Params); } + NodeArray getParams() { return Params; } void printLeft(OutputStream &S) const override { @@ -1030,6 +1133,11 @@ Cache::Unknown), Index(Index_) {} + // We don't provide a matcher for these, because the value of the node is + // not determined by its construction parameters, and it generally needs + // special handling. + template void match(Fn F) const = delete; + bool hasRHSComponentSlow(OutputStream &S) const override { if (Printing) return false; @@ -1077,6 +1185,8 @@ NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_) : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {} + template void match(Fn F) const { F(Name, TemplateArgs); } + StringView getBaseName() const override { return Name->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -1092,6 +1202,8 @@ GlobalQualifiedName(Node* Child_) : Node(KGlobalQualifiedName), Child(Child_) {} + template void match(Fn F) const { F(Child); } + StringView getBaseName() const override { return Child->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -1105,6 +1217,8 @@ StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {} + template void match(Fn F) const { F(Child); } + StringView getBaseName() const override { return Child->getBaseName(); } void printLeft(OutputStream &S) const override { @@ -1129,6 +1243,8 @@ ExpandedSpecialSubstitution(SpecialSubKind SSK_) : Node(KExpandedSpecialSubstitution), SSK(SSK_) {} + template void match(Fn F) const { F(SSK); } + StringView getBaseName() const override { switch (SSK) { case SpecialSubKind::allocator: @@ -1178,6 +1294,8 @@ SpecialSubstitution(SpecialSubKind SSK_) : Node(KSpecialSubstitution), SSK(SSK_) {} + template void match(Fn F) const { F(SSK); } + StringView getBaseName() const override { switch (SSK) { case SpecialSubKind::allocator: @@ -1225,9 +1343,11 @@ const bool IsDtor; public: - CtorDtorName(Node *Basename_, bool IsDtor_) + CtorDtorName(const Node *Basename_, bool IsDtor_) : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {} + template void match(Fn F) const { F(Basename, IsDtor); } + void printLeft(OutputStream &S) const override { if (IsDtor) S += "~"; @@ -1239,7 +1359,9 @@ const Node *Base; public: - DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {} + DtorName(const Node *Base_) : Node(KDtorName), Base(Base_) {} + + template void match(Fn F) const { F(Base); } void printLeft(OutputStream &S) const override { S += "~"; @@ -1253,6 +1375,8 @@ public: UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {} + template void match(Fn F) const { F(Count); } + void printLeft(OutputStream &S) const override { S += "'unnamed"; S += Count; @@ -1268,6 +1392,8 @@ ClosureTypeName(NodeArray Params_, StringView Count_) : Node(KClosureTypeName), Params(Params_), Count(Count_) {} + template void match(Fn F) const { F(Params, Count); } + void printLeft(OutputStream &S) const override { S += "\'lambda"; S += Count; @@ -1283,6 +1409,8 @@ StructuredBindingName(NodeArray Bindings_) : Node(KStructuredBindingName), Bindings(Bindings_) {} + template void match(Fn F) const { F(Bindings); } + void printLeft(OutputStream &S) const override { S += '['; Bindings.printWithComma(S); @@ -1292,18 +1420,17 @@ // -- Expression Nodes -- -struct Expr : public Node { - Expr(Kind K = KExpr) : Node(K) {} -}; - -class BinaryExpr : public Expr { +class BinaryExpr : public Node { const Node *LHS; const StringView InfixOperator; const Node *RHS; public: - BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_) - : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {} + BinaryExpr(const Node *LHS_, StringView InfixOperator_, const Node *RHS_) + : Node(KBinaryExpr), LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) { + } + + template void match(Fn F) const { F(LHS, InfixOperator, RHS); } void printLeft(OutputStream &S) const override { // might be a template argument expression, then we need to disambiguate @@ -1324,12 +1451,15 @@ } }; -class ArraySubscriptExpr : public Expr { +class ArraySubscriptExpr : public Node { const Node *Op1; const Node *Op2; public: - ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {} + ArraySubscriptExpr(const Node *Op1_, const Node *Op2_) + : Node(KArraySubscriptExpr), Op1(Op1_), Op2(Op2_) {} + + template void match(Fn F) const { F(Op1, Op2); } void printLeft(OutputStream &S) const override { S += "("; @@ -1340,30 +1470,34 @@ } }; -class PostfixExpr : public Expr { +class PostfixExpr : public Node { const Node *Child; - const StringView Operand; + const StringView Operator; public: - PostfixExpr(Node *Child_, StringView Operand_) - : Child(Child_), Operand(Operand_) {} + PostfixExpr(const Node *Child_, StringView Operator_) + : Node(KPostfixExpr), Child(Child_), Operator(Operator_) {} + + template void match(Fn F) const { F(Child, Operator); } void printLeft(OutputStream &S) const override { S += "("; Child->print(S); S += ")"; - S += Operand; + S += Operator; } }; -class ConditionalExpr : public Expr { +class ConditionalExpr : public Node { const Node *Cond; const Node *Then; const Node *Else; public: - ConditionalExpr(Node *Cond_, Node *Then_, Node *Else_) - : Cond(Cond_), Then(Then_), Else(Else_) {} + ConditionalExpr(const Node *Cond_, const Node *Then_, const Node *Else_) + : Node(KConditionalExpr), Cond(Cond_), Then(Then_), Else(Else_) {} + + template void match(Fn F) const { F(Cond, Then, Else); } void printLeft(OutputStream &S) const override { S += "("; @@ -1376,14 +1510,16 @@ } }; -class MemberExpr : public Expr { +class MemberExpr : public Node { const Node *LHS; const StringView Kind; const Node *RHS; public: - MemberExpr(Node *LHS_, StringView Kind_, Node *RHS_) - : LHS(LHS_), Kind(Kind_), RHS(RHS_) {} + MemberExpr(const Node *LHS_, StringView Kind_, const Node *RHS_) + : Node(KMemberExpr), LHS(LHS_), Kind(Kind_), RHS(RHS_) {} + + template void match(Fn F) const { F(LHS, Kind, RHS); } void printLeft(OutputStream &S) const override { LHS->print(S); @@ -1392,14 +1528,17 @@ } }; -class EnclosingExpr : public Expr { +class EnclosingExpr : public Node { const StringView Prefix; const Node *Infix; const StringView Postfix; public: EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_) - : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {} + : Node(KEnclosingExpr), Prefix(Prefix_), Infix(Infix_), + Postfix(Postfix_) {} + + template void match(Fn F) const { F(Prefix, Infix, Postfix); } void printLeft(OutputStream &S) const override { S += Prefix; @@ -1408,15 +1547,17 @@ } }; -class CastExpr : public Expr { +class CastExpr : public Node { // cast_kind(from) const StringView CastKind; const Node *To; const Node *From; public: - CastExpr(StringView CastKind_, Node *To_, Node *From_) - : CastKind(CastKind_), To(To_), From(From_) {} + CastExpr(StringView CastKind_, const Node *To_, const Node *From_) + : Node(KCastExpr), CastKind(CastKind_), To(To_), From(From_) {} + + template void match(Fn F) const { F(CastKind, To, From); } void printLeft(OutputStream &S) const override { S += CastKind; @@ -1428,11 +1569,14 @@ } }; -class SizeofParamPackExpr : public Expr { - Node *Pack; +class SizeofParamPackExpr : public Node { + const Node *Pack; public: - SizeofParamPackExpr(Node *Pack_) : Pack(Pack_) {} + SizeofParamPackExpr(const Node *Pack_) + : Node(KSizeofParamPackExpr), Pack(Pack_) {} + + template void match(Fn F) const { F(Pack); } void printLeft(OutputStream &S) const override { S += "sizeof...("; @@ -1442,12 +1586,15 @@ } }; -class CallExpr : public Expr { +class CallExpr : public Node { const Node *Callee; NodeArray Args; public: - CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {} + CallExpr(const Node *Callee_, NodeArray Args_) + : Node(KCallExpr), Callee(Callee_), Args(Args_) {} + + template void match(Fn F) const { F(Callee, Args); } void printLeft(OutputStream &S) const override { Callee->print(S); @@ -1457,7 +1604,7 @@ } }; -class NewExpr : public Expr { +class NewExpr : public Node { // new (expr_list) type(init_list) NodeArray ExprList; Node *Type; @@ -1467,9 +1614,13 @@ public: NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_, bool IsArray_) - : ExprList(ExprList_), Type(Type_), InitList(InitList_), + : Node(KNewExpr), ExprList(ExprList_), Type(Type_), InitList(InitList_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} + template void match(Fn F) const { + F(ExprList, Type, InitList, IsGlobal, IsArray); + } + void printLeft(OutputStream &S) const override { if (IsGlobal) S += "::operator "; @@ -1492,14 +1643,16 @@ } }; -class DeleteExpr : public Expr { +class DeleteExpr : public Node { Node *Op; bool IsGlobal; bool IsArray; public: DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_) - : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} + : Node(KDeleteExpr), Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} + + template void match(Fn F) const { F(Op, IsGlobal, IsArray); } void printLeft(OutputStream &S) const override { if (IsGlobal) @@ -1511,12 +1664,15 @@ } }; -class PrefixExpr : public Expr { +class PrefixExpr : public Node { StringView Prefix; Node *Child; public: - PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {} + PrefixExpr(StringView Prefix_, Node *Child_) + : Node(KPrefixExpr), Prefix(Prefix_), Child(Child_) {} + + template void match(Fn F) const { F(Prefix, Child); } void printLeft(OutputStream &S) const override { S += Prefix; @@ -1526,11 +1682,13 @@ } }; -class FunctionParam : public Expr { +class FunctionParam : public Node { StringView Number; public: - FunctionParam(StringView Number_) : Number(Number_) {} + FunctionParam(StringView Number_) : Node(KFunctionParam), Number(Number_) {} + + template void match(Fn F) const { F(Number); } void printLeft(OutputStream &S) const override { S += "fp"; @@ -1538,13 +1696,15 @@ } }; -class ConversionExpr : public Expr { +class ConversionExpr : public Node { const Node *Type; NodeArray Expressions; public: ConversionExpr(const Node *Type_, NodeArray Expressions_) - : Type(Type_), Expressions(Expressions_) {} + : Node(KConversionExpr), Type(Type_), Expressions(Expressions_) {} + + template void match(Fn F) const { F(Type, Expressions); } void printLeft(OutputStream &S) const override { S += "("; @@ -1555,11 +1715,14 @@ } }; -class InitListExpr : public Expr { - Node *Ty; +class InitListExpr : public Node { + const Node *Ty; NodeArray Inits; public: - InitListExpr(Node *Ty_, NodeArray Inits_) : Ty(Ty_), Inits(Inits_) {} + InitListExpr(const Node *Ty_, NodeArray Inits_) + : Node(KInitListExpr), Ty(Ty_), Inits(Inits_) {} + + template void match(Fn F) const { F(Ty, Inits); } void printLeft(OutputStream &S) const override { if (Ty) @@ -1570,13 +1733,15 @@ } }; -class BracedExpr : public Expr { - Node *Elem; - Node *Init; +class BracedExpr : public Node { + const Node *Elem; + const Node *Init; bool IsArray; public: - BracedExpr(Node *Elem_, Node *Init_, bool IsArray_) - : Expr(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {} + BracedExpr(const Node *Elem_, const Node *Init_, bool IsArray_) + : Node(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {} + + template void match(Fn F) const { F(Elem, Init, IsArray); } void printLeft(OutputStream &S) const override { if (IsArray) { @@ -1593,13 +1758,15 @@ } }; -class BracedRangeExpr : public Expr { - Node *First; - Node *Last; - Node *Init; +class BracedRangeExpr : public Node { + const Node *First; + const Node *Last; + const Node *Init; public: - BracedRangeExpr(Node *First_, Node *Last_, Node *Init_) - : Expr(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {} + BracedRangeExpr(const Node *First_, const Node *Last_, const Node *Init_) + : Node(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {} + + template void match(Fn F) const { F(First, Last, Init); } void printLeft(OutputStream &S) const override { S += '['; @@ -1613,15 +1780,21 @@ } }; -struct FoldExpr : Expr { - Node *Pack, *Init; +class FoldExpr : public Node { + const Node *Pack, *Init; StringView OperatorName; bool IsLeftFold; - FoldExpr(bool IsLeftFold_, StringView OperatorName_, Node *Pack_, Node *Init_) - : Pack(Pack_), Init(Init_), OperatorName(OperatorName_), +public: + FoldExpr(bool IsLeftFold_, StringView OperatorName_, const Node *Pack_, + const Node *Init_) + : Node(KFoldExpr), Pack(Pack_), Init(Init_), OperatorName(OperatorName_), IsLeftFold(IsLeftFold_) {} + template void match(Fn F) const { + F(IsLeftFold, OperatorName, Pack, Init); + } + void printLeft(OutputStream &S) const override { auto PrintPack = [&] { S += '('; @@ -1662,11 +1835,13 @@ } }; -class ThrowExpr : public Expr { +class ThrowExpr : public Node { const Node *Op; public: - ThrowExpr(Node *Op_) : Op(Op_) {} + ThrowExpr(const Node *Op_) : Node(KThrowExpr), Op(Op_) {} + + template void match(Fn F) const { F(Op); } void printLeft(OutputStream &S) const override { S += "throw "; @@ -1674,25 +1849,29 @@ } }; -class BoolExpr : public Expr { +class BoolExpr : public Node { bool Value; public: - BoolExpr(bool Value_) : Value(Value_) {} + BoolExpr(bool Value_) : Node(KBoolExpr), Value(Value_) {} + + template void match(Fn F) const { F(Value); } void printLeft(OutputStream &S) const override { S += Value ? StringView("true") : StringView("false"); } }; -class IntegerCastExpr : public Expr { +class IntegerCastExpr : public Node { // ty(integer) - Node *Ty; + const Node *Ty; StringView Integer; public: - IntegerCastExpr(Node *Ty_, StringView Integer_) - : Ty(Ty_), Integer(Integer_) {} + IntegerCastExpr(const Node *Ty_, StringView Integer_) + : Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {} + + template void match(Fn F) const { F(Ty, Integer); } void printLeft(OutputStream &S) const override { S += "("; @@ -1702,12 +1881,15 @@ } }; -class IntegerExpr : public Expr { +class IntegerLiteral : public Node { StringView Type; StringView Value; public: - IntegerExpr(StringView Type_, StringView Value_) : Type(Type_), Value(Value_) {} + IntegerLiteral(StringView Type_, StringView Value_) + : Node(KIntegerLiteral), Type(Type_), Value(Value_) {} + + template void match(Fn F) const { F(Type, Value); } void printLeft(OutputStream &S) const override { if (Type.size() > 3) { @@ -1729,11 +1911,29 @@ template struct FloatData; -template class FloatExpr : public Expr { +namespace float_literal_impl { +constexpr Node::Kind getFloatLiteralKind(float *) { + return Node::KFloatLiteral; +} +constexpr Node::Kind getFloatLiteralKind(double *) { + return Node::KDoubleLiteral; +} +constexpr Node::Kind getFloatLiteralKind(long double *) { + return Node::KLongDoubleLiteral; +} +} + +template class FloatLiteralImpl : public Node { const StringView Contents; + static constexpr Kind KindForClass = + float_literal_impl::getFloatLiteralKind((Float *)nullptr); + public: - FloatExpr(StringView Contents_) : Contents(Contents_) {} + FloatLiteralImpl(StringView Contents_) + : Node(KindForClass), Contents(Contents_) {} + + template void match(Fn F) const { F(Contents); } void printLeft(OutputStream &s) const override { const char *first = Contents.begin(); @@ -1766,62 +1966,32 @@ } }; -class BumpPointerAllocator { - struct BlockMeta { - BlockMeta* Next; - size_t Current; +using FloatLiteral = FloatLiteralImpl; +using DoubleLiteral = FloatLiteralImpl; +using LongDoubleLiteral = FloatLiteralImpl; + +/// Visit the most-derived object corresponding to a node object. +template +void Node::visit(Fn F) const { + switch (K) { +#define CASE(X) case K ## X: return F(static_cast(this)); + FOR_EACH_NODE_KIND(CASE) +#undef CASE + } + assert(0 && "unknown mangling node kind"); +} + +/// Determine the kind of a node from its type. +template struct NodeKind; +#define SPECIALIZATION(X) \ + template<> struct NodeKind { \ + static constexpr Node::Kind Kind = Node::K##X; \ + static constexpr const char *name() { return #X; } \ }; +FOR_EACH_NODE_KIND(SPECIALIZATION) +#undef SPECIALIZATION - static constexpr size_t AllocSize = 4096; - static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta); - - alignas(long double) char InitialBuffer[AllocSize]; - BlockMeta* BlockList = nullptr; - - void grow() { - char* NewMeta = static_cast(std::malloc(AllocSize)); - if (NewMeta == nullptr) - std::terminate(); - BlockList = new (NewMeta) BlockMeta{BlockList, 0}; - } - - void* allocateMassive(size_t NBytes) { - NBytes += sizeof(BlockMeta); - BlockMeta* NewMeta = reinterpret_cast(std::malloc(NBytes)); - if (NewMeta == nullptr) - std::terminate(); - BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0}; - return static_cast(NewMeta + 1); - } - -public: - BumpPointerAllocator() - : BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {} - - void* allocate(size_t N) { - N = (N + 15u) & ~15u; - if (N + BlockList->Current >= UsableAllocSize) { - if (N > UsableAllocSize) - return allocateMassive(N); - grow(); - } - BlockList->Current += N; - return static_cast(reinterpret_cast(BlockList + 1) + - BlockList->Current - N); - } - - void reset() { - while (BlockList) { - BlockMeta* Tmp = BlockList; - BlockList = BlockList->Next; - if (reinterpret_cast(Tmp) != InitialBuffer) - std::free(Tmp); - } - BlockList = new (InitialBuffer) BlockMeta{nullptr, 0}; - } - - ~BumpPointerAllocator() { reset(); } -}; +#undef FOR_EACH_NODE_KIND template class PODSmallVector { @@ -1942,23 +2112,7 @@ } }; -class DefaultAllocator { - BumpPointerAllocator Alloc; - -public: - void reset() { Alloc.reset(); } - - template T *makeNode(Args &&...args) { - return new (Alloc.allocate(sizeof(T))) - T(std::forward(args)...); - } - - void *allocateNodeArray(size_t sz) { - return Alloc.allocate(sizeof(Node *) * sz); - } -}; - -template +template struct Db { const char *First; const char *Last; @@ -2604,7 +2758,7 @@ // extension ::= D5 # ? template Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) { - if (SoFar->K == Node::KSpecialSubstitution) { + if (SoFar->getKind() == Node::KSpecialSubstitution) { auto SSK = static_cast(SoFar)->SSK; switch (SSK) { case SpecialSubKind::string: @@ -3054,7 +3208,7 @@ if (!consumeIf('_')) return nullptr; if (consumeIf('p')) - return make(DimensionNumber); + return make(DimensionNumber); Node *ElemType = parseType(); if (ElemType == nullptr) return nullptr; @@ -3573,7 +3727,7 @@ template Node *Db::parseIntegerLiteral(StringView Lit) { StringView Tmp = parseNumber(true); if (!Tmp.empty() && consumeIf('E')) - return make(Lit, Tmp); + return make(Lit, Tmp); return nullptr; } @@ -3581,11 +3735,11 @@ template Qualifiers Db::parseCVQualifiers() { Qualifiers CVR = QualNone; if (consumeIf('r')) - addQualifiers(CVR, QualRestrict); + CVR |= QualRestrict; if (consumeIf('V')) - addQualifiers(CVR, QualVolatile); + CVR |= QualVolatile; if (consumeIf('K')) - addQualifiers(CVR, QualConst); + CVR |= QualConst; return CVR; } @@ -4636,8 +4790,6 @@ static constexpr const char* spec = "%af"; }; -constexpr const char* FloatData::spec; - template <> struct FloatData { @@ -4646,8 +4798,6 @@ static constexpr const char* spec = "%a"; }; -constexpr const char* FloatData::spec; - template <> struct FloatData { @@ -4663,8 +4813,6 @@ static constexpr const char *spec = "%LaL"; }; -constexpr const char *FloatData::spec; - template template Node *Db::parseFloatingLiteral() { @@ -4678,7 +4826,7 @@ First += N; if (!consumeIf('E')) return nullptr; - return make>(Data); + return make>(Data); } // ::= <0-9A-Z>+ @@ -4888,44 +5036,6 @@ return make(popTrailingNodeArray(ArgsBegin)); } -// := _ # when number < 10 -// := __ _ # when number >= 10 -// extension := decimal-digit+ # at the end of string - -const char* -parse_discriminator(const char* first, const char* last) -{ - // parse but ignore discriminator - if (first != last) - { - if (*first == '_') - { - const char* t1 = first+1; - if (t1 != last) - { - if (std::isdigit(*t1)) - first = t1+1; - else if (*t1 == '_') - { - for (++t1; t1 != last && std::isdigit(*t1); ++t1) - ; - if (t1 != last && *t1 == '_') - first = t1 + 1; - } - } - } - else if (std::isdigit(*first)) - { - const char* t1 = first+1; - for (; t1 != last && std::isdigit(*t1); ++t1) - ; - if (t1 == last) - first = last; - } - } - return first; -} - // ::= _Z // ::= // extension ::= ___Z _block_invoke @@ -4965,282 +5075,7 @@ return Ty; } -bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S, - size_t InitSize) { - size_t BufferSize; - if (Buf == nullptr) { - Buf = static_cast(std::malloc(InitSize)); - if (Buf == nullptr) - return true; - BufferSize = InitSize; - } else - BufferSize = *N; - - S.reset(Buf, BufferSize); - return false; -} - -} // unnamed namespace - -char *llvm::itaniumDemangle(const char *MangledName, char *Buf, - size_t *N, int *Status) { - if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) { - if (Status) - *Status = demangle_invalid_args; - return nullptr; - } - - int InternalStatus = demangle_success; - Db<> Parser(MangledName, MangledName + std::strlen(MangledName)); - OutputStream S; - - Node *AST = Parser.parse(); - - if (AST == nullptr) - InternalStatus = demangle_invalid_mangled_name; - else if (initializeOutputStream(Buf, N, S, 1024)) - InternalStatus = demangle_memory_alloc_failure; - else { - assert(Parser.ForwardTemplateRefs.empty()); - AST->print(S); - S += '\0'; - if (N != nullptr) - *N = S.getCurrentPosition(); - Buf = S.getBuffer(); - } - - if (Status) - *Status = InternalStatus; - return InternalStatus == demangle_success ? Buf : nullptr; -} - -bool llvm::itaniumFindTypesInMangledName(const char *MangledName, void *Ctx, - void (*Callback)(void *, - const char *)) { - Db<> Parser(MangledName, MangledName + std::strlen(MangledName)); - Parser.TypeCallback = Callback; - Parser.TypeCallbackContext = Ctx; - return Parser.parse() == nullptr; -} - -namespace llvm { - -ItaniumPartialDemangler::ItaniumPartialDemangler() - : RootNode(nullptr), Context(new Db<>{nullptr, nullptr}) {} - -ItaniumPartialDemangler::~ItaniumPartialDemangler() { - delete static_cast *>(Context); -} - -ItaniumPartialDemangler::ItaniumPartialDemangler( - ItaniumPartialDemangler &&Other) - : RootNode(Other.RootNode), Context(Other.Context) { - Other.Context = Other.RootNode = nullptr; -} - -ItaniumPartialDemangler &ItaniumPartialDemangler:: -operator=(ItaniumPartialDemangler &&Other) { - std::swap(RootNode, Other.RootNode); - std::swap(Context, Other.Context); - return *this; -} - -// Demangle MangledName into an AST, storing it into this->RootNode. -bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) { - Db<> *Parser = static_cast *>(Context); - size_t Len = std::strlen(MangledName); - Parser->reset(MangledName, MangledName + Len); - RootNode = Parser->parse(); - return RootNode == nullptr; -} - -static char *printNode(Node *RootNode, char *Buf, size_t *N) { - OutputStream S; - if (initializeOutputStream(Buf, N, S, 128)) - return nullptr; - RootNode->print(S); - S += '\0'; - if (N != nullptr) - *N = S.getCurrentPosition(); - return S.getBuffer(); -} - -char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const { - if (!isFunction()) - return nullptr; - - Node *Name = static_cast(RootNode)->getName(); - - while (true) { - switch (Name->getKind()) { - case Node::KAbiTagAttr: - Name = static_cast(Name)->Base; - continue; - case Node::KStdQualifiedName: - Name = static_cast(Name)->Child; - continue; - case Node::KNestedName: - Name = static_cast(Name)->Name; - continue; - case Node::KLocalName: - Name = static_cast(Name)->Entity; - continue; - case Node::KNameWithTemplateArgs: - Name = static_cast(Name)->Name; - continue; - default: - return printNode(Name, Buf, N); - } - } -} - -char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf, - size_t *N) const { - if (!isFunction()) - return nullptr; - Node *Name = static_cast(RootNode)->getName(); - - OutputStream S; - if (initializeOutputStream(Buf, N, S, 128)) - return nullptr; - - KeepGoingLocalFunction: - while (true) { - if (Name->getKind() == Node::KAbiTagAttr) { - Name = static_cast(Name)->Base; - continue; - } - if (Name->getKind() == Node::KNameWithTemplateArgs) { - Name = static_cast(Name)->Name; - continue; - } - break; - } - - switch (Name->getKind()) { - case Node::KStdQualifiedName: - S += "std"; - break; - case Node::KNestedName: - static_cast(Name)->Qual->print(S); - break; - case Node::KLocalName: { - auto *LN = static_cast(Name); - LN->Encoding->print(S); - S += "::"; - Name = LN->Entity; - goto KeepGoingLocalFunction; - } - default: - break; - } - S += '\0'; - if (N != nullptr) - *N = S.getCurrentPosition(); - return S.getBuffer(); -} - -char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const { - if (!isFunction()) - return nullptr; - auto *Name = static_cast(RootNode)->getName(); - return printNode(Name, Buf, N); -} - -char *ItaniumPartialDemangler::getFunctionParameters(char *Buf, - size_t *N) const { - if (!isFunction()) - return nullptr; - NodeArray Params = static_cast(RootNode)->getParams(); - - OutputStream S; - if (initializeOutputStream(Buf, N, S, 128)) - return nullptr; - - S += '('; - Params.printWithComma(S); - S += ')'; - S += '\0'; - if (N != nullptr) - *N = S.getCurrentPosition(); - return S.getBuffer(); -} - -char *ItaniumPartialDemangler::getFunctionReturnType( - char *Buf, size_t *N) const { - if (!isFunction()) - return nullptr; - - OutputStream S; - if (initializeOutputStream(Buf, N, S, 128)) - return nullptr; - - if (Node *Ret = static_cast(RootNode)->getReturnType()) - Ret->print(S); - - S += '\0'; - if (N != nullptr) - *N = S.getCurrentPosition(); - return S.getBuffer(); -} - -char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const { - assert(RootNode != nullptr && "must call partialDemangle()"); - return printNode(static_cast(RootNode), Buf, N); -} - -bool ItaniumPartialDemangler::hasFunctionQualifiers() const { - assert(RootNode != nullptr && "must call partialDemangle()"); - if (!isFunction()) - return false; - auto *E = static_cast(RootNode); - return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone; -} - -bool ItaniumPartialDemangler::isCtorOrDtor() const { - Node *N = static_cast(RootNode); - while (N) { - switch (N->getKind()) { - default: - return false; - case Node::KCtorDtorName: - return true; - - case Node::KAbiTagAttr: - N = static_cast(N)->Base; - break; - case Node::KFunctionEncoding: - N = static_cast(N)->getName(); - break; - case Node::KLocalName: - N = static_cast(N)->Entity; - break; - case Node::KNameWithTemplateArgs: - N = static_cast(N)->Name; - break; - case Node::KNestedName: - N = static_cast(N)->Name; - break; - case Node::KStdQualifiedName: - N = static_cast(N)->Child; - break; - } - } - return false; -} - -bool ItaniumPartialDemangler::isFunction() const { - assert(RootNode != nullptr && "must call partialDemangle()"); - return static_cast(RootNode)->getKind() == Node::KFunctionEncoding; -} - -bool ItaniumPartialDemangler::isSpecialName() const { - assert(RootNode != nullptr && "must call partialDemangle()"); - auto K = static_cast(RootNode)->getKind(); - return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName; -} - -bool ItaniumPartialDemangler::isData() const { - return !isFunction() && !isSpecialName(); -} +} // namespace itanium_demangle } // namespace llvm + +#endif // LLVM_DEMANGLE_ITANIUMDEMANGLE_H Index: lib/Demangle/Compiler.h =================================================================== --- /dev/null +++ lib/Demangle/Compiler.h @@ -1,93 +0,0 @@ -//===--- Compiler.h ---------------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -// -// This file contains a variety of feature test macros copied from -// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take -// a dependency on LLVMSupport. -//===----------------------------------------------------------------------===// - -#ifndef LLVM_DEMANGLE_COMPILER_H -#define LLVM_DEMANGLE_COMPILER_H - -#ifdef _MSC_VER -// snprintf is implemented in VS 2015 -#if _MSC_VER < 1900 -#define snprintf _snprintf_s -#endif -#endif - -#ifndef __has_feature -#define __has_feature(x) 0 -#endif - -#ifndef __has_cpp_attribute -#define __has_cpp_attribute(x) 0 -#endif - -#ifndef __has_attribute -#define __has_attribute(x) 0 -#endif - -#ifndef __has_builtin -#define __has_builtin(x) 0 -#endif - -#ifndef LLVM_GNUC_PREREQ -#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \ - ((maj) << 20) + ((min) << 10) + (patch)) -#elif defined(__GNUC__) && defined(__GNUC_MINOR__) -#define LLVM_GNUC_PREREQ(maj, min, patch) \ - ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10)) -#else -#define LLVM_GNUC_PREREQ(maj, min, patch) 0 -#endif -#endif - -#if __has_attribute(used) || LLVM_GNUC_PREREQ(3, 1, 0) -#define LLVM_ATTRIBUTE_USED __attribute__((__used__)) -#else -#define LLVM_ATTRIBUTE_USED -#endif - -#if __has_builtin(__builtin_unreachable) || LLVM_GNUC_PREREQ(4, 5, 0) -#define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() -#elif defined(_MSC_VER) -#define LLVM_BUILTIN_UNREACHABLE __assume(false) -#endif - -#if __has_attribute(noinline) || LLVM_GNUC_PREREQ(3, 4, 0) -#define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) -#elif defined(_MSC_VER) -#define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) -#else -#define LLVM_ATTRIBUTE_NOINLINE -#endif - -#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE LLVM_ATTRIBUTE_USED -#else -#define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE -#endif - -#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough) -#define LLVM_FALLTHROUGH [[fallthrough]] -#elif __has_cpp_attribute(gnu::fallthrough) -#define LLVM_FALLTHROUGH [[gnu::fallthrough]] -#elif !__cplusplus -// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious -// error when __has_cpp_attribute is given a scoped attribute in C mode. -#define LLVM_FALLTHROUGH -#elif __has_cpp_attribute(clang::fallthrough) -#define LLVM_FALLTHROUGH [[clang::fallthrough]] -#else -#define LLVM_FALLTHROUGH -#endif - -#endif Index: lib/Demangle/ItaniumDemangle.cpp =================================================================== --- lib/Demangle/ItaniumDemangle.cpp +++ lib/Demangle/ItaniumDemangle.cpp @@ -11,10 +11,8 @@ // file does not yet support: // - C++ modules TS -#include "Compiler.h" -#include "StringView.h" -#include "Utility.h" #include "llvm/Demangle/Demangle.h" +#include "llvm/Demangle/ItaniumDemangle.h" #include #include @@ -25,1747 +23,221 @@ #include #include -namespace { -// Base class of all AST nodes. The AST is built by the parser, then is -// traversed by the printLeft/Right functions to produce a demangled string. -class Node { -public: - enum Kind : unsigned char { - KNodeArrayNode, - KDotSuffix, - KVendorExtQualType, - KQualType, - KConversionOperatorType, - KPostfixQualifiedType, - KElaboratedTypeSpefType, - KNameType, - KAbiTagAttr, - KEnableIfAttr, - KObjCProtoName, - KPointerType, - KReferenceType, - KPointerToMemberType, - KArrayType, - KFunctionType, - KNoexceptSpec, - KDynamicExceptionSpec, - KFunctionEncoding, - KLiteralOperator, - KSpecialName, - KCtorVtableSpecialName, - KQualifiedName, - KNestedName, - KLocalName, - KVectorType, - KParameterPack, - KTemplateArgumentPack, - KParameterPackExpansion, - KTemplateArgs, - KForwardTemplateReference, - KNameWithTemplateArgs, - KGlobalQualifiedName, - KStdQualifiedName, - KExpandedSpecialSubstitution, - KSpecialSubstitution, - KCtorDtorName, - KDtorName, - KUnnamedTypeName, - KClosureTypeName, - KStructuredBindingName, - KExpr, - KBracedExpr, - KBracedRangeExpr, - }; - - Kind K; - - /// Three-way bool to track a cached value. Unknown is possible if this node - /// has an unexpanded parameter pack below it that may affect this cache. - enum class Cache : unsigned char { Yes, No, Unknown, }; - - /// Tracks if this node has a component on its right side, in which case we - /// need to call printRight. - Cache RHSComponentCache; - - /// Track if this node is a (possibly qualified) array type. This can affect - /// how we format the output string. - Cache ArrayCache; - - /// Track if this node is a (possibly qualified) function type. This can - /// affect how we format the output string. - Cache FunctionCache; - - Node(Kind K_, Cache RHSComponentCache_ = Cache::No, - Cache ArrayCache_ = Cache::No, Cache FunctionCache_ = Cache::No) - : K(K_), RHSComponentCache(RHSComponentCache_), ArrayCache(ArrayCache_), - FunctionCache(FunctionCache_) {} - - bool hasRHSComponent(OutputStream &S) const { - if (RHSComponentCache != Cache::Unknown) - return RHSComponentCache == Cache::Yes; - return hasRHSComponentSlow(S); - } - - bool hasArray(OutputStream &S) const { - if (ArrayCache != Cache::Unknown) - return ArrayCache == Cache::Yes; - return hasArraySlow(S); - } - - bool hasFunction(OutputStream &S) const { - if (FunctionCache != Cache::Unknown) - return FunctionCache == Cache::Yes; - return hasFunctionSlow(S); +using namespace llvm::itanium_demangle; + +constexpr const char *llvm::itanium_demangle::FloatData::spec; +constexpr const char *llvm::itanium_demangle::FloatData::spec; +constexpr const char *llvm::itanium_demangle::FloatData::spec; + +// := _ # when number < 10 +// := __ _ # when number >= 10 +// extension := decimal-digit+ # at the end of string +const char *llvm::itanium_demangle::parse_discriminator(const char *first, + const char *last) { + // parse but ignore discriminator + if (first != last) { + if (*first == '_') { + const char *t1 = first + 1; + if (t1 != last) { + if (std::isdigit(*t1)) + first = t1 + 1; + else if (*t1 == '_') { + for (++t1; t1 != last && std::isdigit(*t1); ++t1) + ; + if (t1 != last && *t1 == '_') + first = t1 + 1; + } + } + } else if (std::isdigit(*first)) { + const char *t1 = first + 1; + for (; t1 != last && std::isdigit(*t1); ++t1) + ; + if (t1 == last) + first = last; + } } - - Kind getKind() const { return K; } - - virtual bool hasRHSComponentSlow(OutputStream &) const { return false; } - virtual bool hasArraySlow(OutputStream &) const { return false; } - virtual bool hasFunctionSlow(OutputStream &) const { return false; } - - // Dig through "glue" nodes like ParameterPack and ForwardTemplateReference to - // get at a node that actually represents some concrete syntax. - virtual const Node *getSyntaxNode(OutputStream &) const { - return this; - } - - void print(OutputStream &S) const { - printLeft(S); - if (RHSComponentCache != Cache::No) - printRight(S); - } - - // Print the "left" side of this Node into OutputStream. - virtual void printLeft(OutputStream &) const = 0; - - // Print the "right". This distinction is necessary to represent C++ types - // that appear on the RHS of their subtype, such as arrays or functions. - // Since most types don't have such a component, provide a default - // implementation. - virtual void printRight(OutputStream &) const {} - - virtual StringView getBaseName() const { return StringView(); } - - // Silence compiler warnings, this dtor will never be called. - virtual ~Node() = default; + return first; +} #ifndef NDEBUG - LLVM_DUMP_METHOD void dump() const { - char *Buffer = static_cast(std::malloc(1024)); - OutputStream S(Buffer, 1024); - print(S); - S += '\0'; - printf("Symbol dump for %p: %s\n", (const void*)this, S.getBuffer()); - std::free(S.getBuffer()); - } -#endif -}; - -class NodeArray { - Node **Elements; - size_t NumElements; - -public: - NodeArray() : Elements(nullptr), NumElements(0) {} - NodeArray(Node **Elements_, size_t NumElements_) - : Elements(Elements_), NumElements(NumElements_) {} - - bool empty() const { return NumElements == 0; } - size_t size() const { return NumElements; } - - Node **begin() const { return Elements; } - Node **end() const { return Elements + NumElements; } - - Node *operator[](size_t Idx) const { return Elements[Idx]; } - - void printWithComma(OutputStream &S) const { - bool FirstElement = true; - for (size_t Idx = 0; Idx != NumElements; ++Idx) { - size_t BeforeComma = S.getCurrentPosition(); - if (!FirstElement) - S += ", "; - size_t AfterComma = S.getCurrentPosition(); - Elements[Idx]->print(S); - - // Elements[Idx] is an empty parameter pack expansion, we should erase the - // comma we just printed. - if (AfterComma == S.getCurrentPosition()) { - S.setCurrentPosition(BeforeComma); - continue; - } - - FirstElement = false; - } - } -}; +struct DumpVisitor { + unsigned Depth = 0; + bool PendingNewline = false; -struct NodeArrayNode : Node { - NodeArray Array; - NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {} - void printLeft(OutputStream &S) const override { - Array.printWithComma(S); + template static constexpr bool wantsNewline(const NodeT *) { + return true; } -}; + static bool wantsNewline(NodeArray A) { return !A.empty(); } + static constexpr bool wantsNewline(...) { return false; } -class DotSuffix final : public Node { - const Node *Prefix; - const StringView Suffix; - -public: - DotSuffix(Node *Prefix_, StringView Suffix_) - : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} - - void printLeft(OutputStream &s) const override { - Prefix->print(s); - s += " ("; - s += Suffix; - s += ")"; - } -}; - -class VendorExtQualType final : public Node { - const Node *Ty; - StringView Ext; - -public: - VendorExtQualType(Node *Ty_, StringView Ext_) - : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} - - void printLeft(OutputStream &S) const override { - Ty->print(S); - S += " "; - S += Ext; + template static bool anyWantNewline(Ts ...Vs) { + for (bool B : {wantsNewline(Vs)...}) + if (B) + return true; + return false; } -}; - -enum FunctionRefQual : unsigned char { - FrefQualNone, - FrefQualLValue, - FrefQualRValue, -}; - -enum Qualifiers { - QualNone = 0, - QualConst = 0x1, - QualVolatile = 0x2, - QualRestrict = 0x4, -}; - -void addQualifiers(Qualifiers &Q1, Qualifiers Q2) { - Q1 = static_cast(Q1 | Q2); -} - -class QualType : public Node { -protected: - const Qualifiers Quals; - const Node *Child; - - void printQuals(OutputStream &S) const { - if (Quals & QualConst) - S += " const"; - if (Quals & QualVolatile) - S += " volatile"; - if (Quals & QualRestrict) - S += " restrict"; - } - -public: - QualType(Node *Child_, Qualifiers Quals_) - : Node(KQualType, Child_->RHSComponentCache, - Child_->ArrayCache, Child_->FunctionCache), - Quals(Quals_), Child(Child_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - return Child->hasRHSComponent(S); - } - bool hasArraySlow(OutputStream &S) const override { - return Child->hasArray(S); - } - bool hasFunctionSlow(OutputStream &S) const override { - return Child->hasFunction(S); - } - - void printLeft(OutputStream &S) const override { - Child->printLeft(S); - printQuals(S); - } - - void printRight(OutputStream &S) const override { Child->printRight(S); } -}; - -class ConversionOperatorType final : public Node { - const Node *Ty; - -public: - ConversionOperatorType(Node *Ty_) - : Node(KConversionOperatorType), Ty(Ty_) {} - - void printLeft(OutputStream &S) const override { - S += "operator "; - Ty->print(S); - } -}; - -class PostfixQualifiedType final : public Node { - const Node *Ty; - const StringView Postfix; - -public: - PostfixQualifiedType(Node *Ty_, StringView Postfix_) - : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} - - void printLeft(OutputStream &s) const override { - Ty->printLeft(s); - s += Postfix; - } -}; - -class NameType final : public Node { - const StringView Name; - -public: - NameType(StringView Name_) : Node(KNameType), Name(Name_) {} - - StringView getName() const { return Name; } - StringView getBaseName() const override { return Name; } - - void printLeft(OutputStream &s) const override { s += Name; } -}; - -class ElaboratedTypeSpefType : public Node { - StringView Kind; - Node *Child; -public: - ElaboratedTypeSpefType(StringView Kind_, Node *Child_) - : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} - - void printLeft(OutputStream &S) const override { - S += Kind; - S += ' '; - Child->print(S); - } -}; - -struct AbiTagAttr : Node { - Node *Base; - StringView Tag; - - AbiTagAttr(Node* Base_, StringView Tag_) - : Node(KAbiTagAttr, Base_->RHSComponentCache, - Base_->ArrayCache, Base_->FunctionCache), - Base(Base_), Tag(Tag_) {} - - void printLeft(OutputStream &S) const override { - Base->printLeft(S); - S += "[abi:"; - S += Tag; - S += "]"; - } -}; - -class EnableIfAttr : public Node { - NodeArray Conditions; -public: - EnableIfAttr(NodeArray Conditions_) - : Node(KEnableIfAttr), Conditions(Conditions_) {} - - void printLeft(OutputStream &S) const override { - S += " [enable_if:"; - Conditions.printWithComma(S); - S += ']'; - } -}; - -class ObjCProtoName : public Node { - Node *Ty; - StringView Protocol; - - friend class PointerType; - -public: - ObjCProtoName(Node *Ty_, StringView Protocol_) - : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} - - bool isObjCObject() const { - return Ty->getKind() == KNameType && - static_cast(Ty)->getName() == "objc_object"; - } - - void printLeft(OutputStream &S) const override { - Ty->print(S); - S += "<"; - S += Protocol; - S += ">"; - } -}; - -class PointerType final : public Node { - const Node *Pointee; - -public: - PointerType(Node *Pointee_) - : Node(KPointerType, Pointee_->RHSComponentCache), - Pointee(Pointee_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - return Pointee->hasRHSComponent(S); - } - - void printLeft(OutputStream &s) const override { - // We rewrite objc_object* into id. - if (Pointee->getKind() != KObjCProtoName || - !static_cast(Pointee)->isObjCObject()) { - Pointee->printLeft(s); - if (Pointee->hasArray(s)) - s += " "; - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += "("; - s += "*"; - } else { - const auto *objcProto = static_cast(Pointee); - s += "id<"; - s += objcProto->Protocol; - s += ">"; - } - } - - void printRight(OutputStream &s) const override { - if (Pointee->getKind() != KObjCProtoName || - !static_cast(Pointee)->isObjCObject()) { - if (Pointee->hasArray(s) || Pointee->hasFunction(s)) - s += ")"; - Pointee->printRight(s); - } - } -}; - -enum class ReferenceKind { - LValue, - RValue, -}; - -// Represents either a LValue or an RValue reference type. -class ReferenceType : public Node { - const Node *Pointee; - ReferenceKind RK; - - mutable bool Printing = false; - - // Dig through any refs to refs, collapsing the ReferenceTypes as we go. The - // rule here is rvalue ref to rvalue ref collapses to a rvalue ref, and any - // other combination collapses to a lvalue ref. - std::pair collapse(OutputStream &S) const { - auto SoFar = std::make_pair(RK, Pointee); - for (;;) { - const Node *SN = SoFar.second->getSyntaxNode(S); - if (SN->getKind() != KReferenceType) - break; - auto *RT = static_cast(SN); - SoFar.second = RT->Pointee; - SoFar.first = std::min(SoFar.first, RT->RK); - } - return SoFar; - } - -public: - ReferenceType(Node *Pointee_, ReferenceKind RK_) - : Node(KReferenceType, Pointee_->RHSComponentCache), - Pointee(Pointee_), RK(RK_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - return Pointee->hasRHSComponent(S); - } - - void printLeft(OutputStream &s) const override { - if (Printing) - return; - SwapAndRestore SavePrinting(Printing, true); - std::pair Collapsed = collapse(s); - Collapsed.second->printLeft(s); - if (Collapsed.second->hasArray(s)) - s += " "; - if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) - s += "("; - - s += (Collapsed.first == ReferenceKind::LValue ? "&" : "&&"); - } - void printRight(OutputStream &s) const override { - if (Printing) - return; - SwapAndRestore SavePrinting(Printing, true); - std::pair Collapsed = collapse(s); - if (Collapsed.second->hasArray(s) || Collapsed.second->hasFunction(s)) - s += ")"; - Collapsed.second->printRight(s); - } -}; - -class PointerToMemberType final : public Node { - const Node *ClassType; - const Node *MemberType; - -public: - PointerToMemberType(Node *ClassType_, Node *MemberType_) - : Node(KPointerToMemberType, MemberType_->RHSComponentCache), - ClassType(ClassType_), MemberType(MemberType_) {} - bool hasRHSComponentSlow(OutputStream &S) const override { - return MemberType->hasRHSComponent(S); + void printStr(const char *S) { fprintf(stderr, "%s", S); } + void print(StringView SV) { + fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin()); } - - void printLeft(OutputStream &s) const override { - MemberType->printLeft(s); - if (MemberType->hasArray(s) || MemberType->hasFunction(s)) - s += "("; + void print(const Node *N) { + if (N) + N->visit(std::ref(*this)); else - s += " "; - ClassType->print(s); - s += "::*"; - } - - void printRight(OutputStream &s) const override { - if (MemberType->hasArray(s) || MemberType->hasFunction(s)) - s += ")"; - MemberType->printRight(s); - } -}; - -class NodeOrString { - const void *First; - const void *Second; - -public: - /* implicit */ NodeOrString(StringView Str) { - const char *FirstChar = Str.begin(); - const char *SecondChar = Str.end(); - if (SecondChar == nullptr) { - assert(FirstChar == SecondChar); - ++FirstChar, ++SecondChar; - } - First = static_cast(FirstChar); - Second = static_cast(SecondChar); - } - - /* implicit */ NodeOrString(Node *N) - : First(static_cast(N)), Second(nullptr) {} - NodeOrString() : First(nullptr), Second(nullptr) {} - - bool isString() const { return Second && First; } - bool isNode() const { return First && !Second; } - bool isEmpty() const { return !First && !Second; } - - StringView asString() const { - assert(isString()); - return StringView(static_cast(First), - static_cast(Second)); - } - - const Node *asNode() const { - assert(isNode()); - return static_cast(First); - } -}; - -class ArrayType final : public Node { - Node *Base; - NodeOrString Dimension; - -public: - ArrayType(Node *Base_, NodeOrString Dimension_) - : Node(KArrayType, - /*RHSComponentCache=*/Cache::Yes, - /*ArrayCache=*/Cache::Yes), - Base(Base_), Dimension(Dimension_) {} - - // Incomplete array type. - ArrayType(Node *Base_) - : Node(KArrayType, - /*RHSComponentCache=*/Cache::Yes, - /*ArrayCache=*/Cache::Yes), - Base(Base_) {} - - bool hasRHSComponentSlow(OutputStream &) const override { return true; } - bool hasArraySlow(OutputStream &) const override { return true; } - - void printLeft(OutputStream &S) const override { Base->printLeft(S); } - - void printRight(OutputStream &S) const override { - if (S.back() != ']') - S += " "; - S += "["; - if (Dimension.isString()) - S += Dimension.asString(); - else if (Dimension.isNode()) - Dimension.asNode()->print(S); - S += "]"; - Base->printRight(S); - } -}; - -class FunctionType final : public Node { - Node *Ret; - NodeArray Params; - Qualifiers CVQuals; - FunctionRefQual RefQual; - Node *ExceptionSpec; - -public: - FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, - FunctionRefQual RefQual_, Node *ExceptionSpec_) - : Node(KFunctionType, - /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, - /*FunctionCache=*/Cache::Yes), - Ret(Ret_), Params(Params_), CVQuals(CVQuals_), RefQual(RefQual_), - ExceptionSpec(ExceptionSpec_) {} - - bool hasRHSComponentSlow(OutputStream &) const override { return true; } - bool hasFunctionSlow(OutputStream &) const override { return true; } - - // Handle C++'s ... quirky decl grammar by using the left & right - // distinction. Consider: - // int (*f(float))(char) {} - // f is a function that takes a float and returns a pointer to a function - // that takes a char and returns an int. If we're trying to print f, start - // by printing out the return types's left, then print our parameters, then - // finally print right of the return type. - void printLeft(OutputStream &S) const override { - Ret->printLeft(S); - S += " "; - } - - void printRight(OutputStream &S) const override { - S += "("; - Params.printWithComma(S); - S += ")"; - Ret->printRight(S); - - if (CVQuals & QualConst) - S += " const"; - if (CVQuals & QualVolatile) - S += " volatile"; - if (CVQuals & QualRestrict) - S += " restrict"; - - if (RefQual == FrefQualLValue) - S += " &"; - else if (RefQual == FrefQualRValue) - S += " &&"; - - if (ExceptionSpec != nullptr) { - S += ' '; - ExceptionSpec->print(S); - } - } -}; - -class NoexceptSpec : public Node { - Node *E; -public: - NoexceptSpec(Node *E_) : Node(KNoexceptSpec), E(E_) {} - - void printLeft(OutputStream &S) const override { - S += "noexcept("; - E->print(S); - S += ")"; - } -}; - -class DynamicExceptionSpec : public Node { - NodeArray Types; -public: - DynamicExceptionSpec(NodeArray Types_) - : Node(KDynamicExceptionSpec), Types(Types_) {} - - void printLeft(OutputStream &S) const override { - S += "throw("; - Types.printWithComma(S); - S += ')'; - } -}; - -class FunctionEncoding final : public Node { - Node *Ret; - Node *Name; - NodeArray Params; - Node *Attrs; - Qualifiers CVQuals; - FunctionRefQual RefQual; - -public: - FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_, - Node *Attrs_, Qualifiers CVQuals_, FunctionRefQual RefQual_) - : Node(KFunctionEncoding, - /*RHSComponentCache=*/Cache::Yes, /*ArrayCache=*/Cache::No, - /*FunctionCache=*/Cache::Yes), - Ret(Ret_), Name(Name_), Params(Params_), Attrs(Attrs_), - CVQuals(CVQuals_), RefQual(RefQual_) {} - - Qualifiers getCVQuals() const { return CVQuals; } - FunctionRefQual getRefQual() const { return RefQual; } - NodeArray getParams() const { return Params; } - Node *getReturnType() const { return Ret; } - - bool hasRHSComponentSlow(OutputStream &) const override { return true; } - bool hasFunctionSlow(OutputStream &) const override { return true; } - - Node *getName() { return const_cast(Name); } - - void printLeft(OutputStream &S) const override { - if (Ret) { - Ret->printLeft(S); - if (!Ret->hasRHSComponent(S)) - S += " "; - } - Name->print(S); - } - - void printRight(OutputStream &S) const override { - S += "("; - Params.printWithComma(S); - S += ")"; - if (Ret) - Ret->printRight(S); - - if (CVQuals & QualConst) - S += " const"; - if (CVQuals & QualVolatile) - S += " volatile"; - if (CVQuals & QualRestrict) - S += " restrict"; - - if (RefQual == FrefQualLValue) - S += " &"; - else if (RefQual == FrefQualRValue) - S += " &&"; - - if (Attrs != nullptr) - Attrs->print(S); - } -}; - -class LiteralOperator : public Node { - const Node *OpName; - -public: - LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {} - - void printLeft(OutputStream &S) const override { - S += "operator\"\" "; - OpName->print(S); - } -}; - -class SpecialName final : public Node { - const StringView Special; - const Node *Child; - -public: - SpecialName(StringView Special_, Node* Child_) - : Node(KSpecialName), Special(Special_), Child(Child_) {} - - void printLeft(OutputStream &S) const override { - S += Special; - Child->print(S); - } -}; - -class CtorVtableSpecialName final : public Node { - const Node *FirstType; - const Node *SecondType; - -public: - CtorVtableSpecialName(Node *FirstType_, Node *SecondType_) - : Node(KCtorVtableSpecialName), - FirstType(FirstType_), SecondType(SecondType_) {} - - void printLeft(OutputStream &S) const override { - S += "construction vtable for "; - FirstType->print(S); - S += "-in-"; - SecondType->print(S); - } -}; - -struct NestedName : Node { - Node *Qual; - Node *Name; - - NestedName(Node *Qual_, Node *Name_) - : Node(KNestedName), Qual(Qual_), Name(Name_) {} - - StringView getBaseName() const override { return Name->getBaseName(); } - - void printLeft(OutputStream &S) const override { - Qual->print(S); - S += "::"; - Name->print(S); - } -}; - -struct LocalName : Node { - Node *Encoding; - Node *Entity; - - LocalName(Node *Encoding_, Node *Entity_) - : Node(KLocalName), Encoding(Encoding_), Entity(Entity_) {} - - void printLeft(OutputStream &S) const override { - Encoding->print(S); - S += "::"; - Entity->print(S); - } -}; - -class QualifiedName final : public Node { - // qualifier::name - const Node *Qualifier; - const Node *Name; - -public: - QualifiedName(Node* Qualifier_, Node* Name_) - : Node(KQualifiedName), Qualifier(Qualifier_), Name(Name_) {} - - StringView getBaseName() const override { return Name->getBaseName(); } - - void printLeft(OutputStream &S) const override { - Qualifier->print(S); - S += "::"; - Name->print(S); - } -}; - -class VectorType final : public Node { - const Node *BaseType; - const NodeOrString Dimension; - const bool IsPixel; - -public: - VectorType(NodeOrString Dimension_) - : Node(KVectorType), BaseType(nullptr), Dimension(Dimension_), - IsPixel(true) {} - VectorType(Node *BaseType_, NodeOrString Dimension_) - : Node(KVectorType), BaseType(BaseType_), - Dimension(Dimension_), IsPixel(false) {} - - void printLeft(OutputStream &S) const override { - if (IsPixel) { - S += "pixel vector["; - S += Dimension.asString(); - S += "]"; - } else { - BaseType->print(S); - S += " vector["; - if (Dimension.isNode()) - Dimension.asNode()->print(S); - else if (Dimension.isString()) - S += Dimension.asString(); - S += "]"; - } - } -}; - -/// An unexpanded parameter pack (either in the expression or type context). If -/// this AST is correct, this node will have a ParameterPackExpansion node above -/// it. -/// -/// This node is created when some are found that apply to an -/// , and is stored in the TemplateParams table. In order for this to -/// appear in the final AST, it has to referenced via a (ie, -/// T_). -class ParameterPack final : public Node { - NodeArray Data; - - // Setup OutputStream for a pack expansion unless we're already expanding one. - void initializePackExpansion(OutputStream &S) const { - if (S.CurrentPackMax == std::numeric_limits::max()) { - S.CurrentPackMax = static_cast(Data.size()); - S.CurrentPackIndex = 0; - } + printStr(""); } - -public: - ParameterPack(NodeArray Data_) : Node(KParameterPack), Data(Data_) { - ArrayCache = FunctionCache = RHSComponentCache = Cache::Unknown; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->ArrayCache == Cache::No; - })) - ArrayCache = Cache::No; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->FunctionCache == Cache::No; - })) - FunctionCache = Cache::No; - if (std::all_of(Data.begin(), Data.end(), [](Node* P) { - return P->RHSComponentCache == Cache::No; - })) - RHSComponentCache = Cache::No; - } - - bool hasRHSComponentSlow(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - return Idx < Data.size() && Data[Idx]->hasRHSComponent(S); - } - bool hasArraySlow(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - return Idx < Data.size() && Data[Idx]->hasArray(S); - } - bool hasFunctionSlow(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - return Idx < Data.size() && Data[Idx]->hasFunction(S); - } - const Node *getSyntaxNode(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - return Idx < Data.size() ? Data[Idx]->getSyntaxNode(S) : this; - } - - void printLeft(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - if (Idx < Data.size()) - Data[Idx]->printLeft(S); - } - void printRight(OutputStream &S) const override { - initializePackExpansion(S); - size_t Idx = S.CurrentPackIndex; - if (Idx < Data.size()) - Data[Idx]->printRight(S); - } -}; - -/// A variadic template argument. This node represents an occurrence of -/// JE in some . It isn't itself unexpanded, unless -/// one of it's Elements is. The parser inserts a ParameterPack into the -/// TemplateParams table if the this pack belongs to apply to an -/// . -class TemplateArgumentPack final : public Node { - NodeArray Elements; -public: - TemplateArgumentPack(NodeArray Elements_) - : Node(KTemplateArgumentPack), Elements(Elements_) {} - - NodeArray getElements() const { return Elements; } - - void printLeft(OutputStream &S) const override { - Elements.printWithComma(S); - } -}; - -/// A pack expansion. Below this node, there are some unexpanded ParameterPacks -/// which each have Child->ParameterPackSize elements. -class ParameterPackExpansion final : public Node { - const Node *Child; - -public: - ParameterPackExpansion(Node* Child_) - : Node(KParameterPackExpansion), Child(Child_) {} - - const Node *getChild() const { return Child; } - - void printLeft(OutputStream &S) const override { - constexpr unsigned Max = std::numeric_limits::max(); - SwapAndRestore SavePackIdx(S.CurrentPackIndex, Max); - SwapAndRestore SavePackMax(S.CurrentPackMax, Max); - size_t StreamPos = S.getCurrentPosition(); - - // Print the first element in the pack. If Child contains a ParameterPack, - // it will set up S.CurrentPackMax and print the first element. - Child->print(S); - - // No ParameterPack was found in Child. This can occur if we've found a pack - // expansion on a . - if (S.CurrentPackMax == Max) { - S += "..."; - return; - } - - // We found a ParameterPack, but it has no elements. Erase whatever we may - // of printed. - if (S.CurrentPackMax == 0) { - S.setCurrentPosition(StreamPos); - return; - } - - // Else, iterate through the rest of the elements in the pack. - for (unsigned I = 1, E = S.CurrentPackMax; I < E; ++I) { - S += ", "; - S.CurrentPackIndex = I; - Child->print(S); - } - } -}; - -class TemplateArgs final : public Node { - NodeArray Params; - -public: - TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} - - NodeArray getParams() { return Params; } - - void printLeft(OutputStream &S) const override { - S += "<"; - Params.printWithComma(S); - if (S.back() == '>') - S += " "; - S += ">"; - } -}; - -struct ForwardTemplateReference : Node { - size_t Index; - Node *Ref = nullptr; - - // If we're currently printing this node. It is possible (though invalid) for - // a forward template reference to refer to itself via a substitution. This - // creates a cyclic AST, which will stack overflow printing. To fix this, bail - // out if more than one print* function is active. - mutable bool Printing = false; - - ForwardTemplateReference(size_t Index_) - : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown, - Cache::Unknown), - Index(Index_) {} - - bool hasRHSComponentSlow(OutputStream &S) const override { - if (Printing) - return false; - SwapAndRestore SavePrinting(Printing, true); - return Ref->hasRHSComponent(S); - } - bool hasArraySlow(OutputStream &S) const override { - if (Printing) - return false; - SwapAndRestore SavePrinting(Printing, true); - return Ref->hasArray(S); - } - bool hasFunctionSlow(OutputStream &S) const override { - if (Printing) - return false; - SwapAndRestore SavePrinting(Printing, true); - return Ref->hasFunction(S); - } - const Node *getSyntaxNode(OutputStream &S) const override { - if (Printing) - return this; - SwapAndRestore SavePrinting(Printing, true); - return Ref->getSyntaxNode(S); - } - - void printLeft(OutputStream &S) const override { - if (Printing) - return; - SwapAndRestore SavePrinting(Printing, true); - Ref->printLeft(S); - } - void printRight(OutputStream &S) const override { - if (Printing) - return; - SwapAndRestore SavePrinting(Printing, true); - Ref->printRight(S); - } -}; - -struct NameWithTemplateArgs : Node { - // name - Node *Name; - Node *TemplateArgs; - - NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_) - : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {} - - StringView getBaseName() const override { return Name->getBaseName(); } - - void printLeft(OutputStream &S) const override { - Name->print(S); - TemplateArgs->print(S); - } -}; - -class GlobalQualifiedName final : public Node { - Node *Child; - -public: - GlobalQualifiedName(Node* Child_) - : Node(KGlobalQualifiedName), Child(Child_) {} - - StringView getBaseName() const override { return Child->getBaseName(); } - - void printLeft(OutputStream &S) const override { - S += "::"; - Child->print(S); - } -}; - -struct StdQualifiedName : Node { - Node *Child; - - StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {} - - StringView getBaseName() const override { return Child->getBaseName(); } - - void printLeft(OutputStream &S) const override { - S += "std::"; - Child->print(S); - } -}; - -enum class SpecialSubKind { - allocator, - basic_string, - string, - istream, - ostream, - iostream, -}; - -class ExpandedSpecialSubstitution final : public Node { - SpecialSubKind SSK; - -public: - ExpandedSpecialSubstitution(SpecialSubKind SSK_) - : Node(KExpandedSpecialSubstitution), SSK(SSK_) {} - - StringView getBaseName() const override { - switch (SSK) { - case SpecialSubKind::allocator: - return StringView("allocator"); - case SpecialSubKind::basic_string: - return StringView("basic_string"); - case SpecialSubKind::string: - return StringView("basic_string"); - case SpecialSubKind::istream: - return StringView("basic_istream"); - case SpecialSubKind::ostream: - return StringView("basic_ostream"); - case SpecialSubKind::iostream: - return StringView("basic_iostream"); - } - LLVM_BUILTIN_UNREACHABLE; - } - - void printLeft(OutputStream &S) const override { - switch (SSK) { - case SpecialSubKind::allocator: - S += "std::basic_string, " - "std::allocator >"; - break; - case SpecialSubKind::basic_string: - case SpecialSubKind::string: - S += "std::basic_string, " - "std::allocator >"; - break; - case SpecialSubKind::istream: - S += "std::basic_istream >"; - break; - case SpecialSubKind::ostream: - S += "std::basic_ostream >"; - break; - case SpecialSubKind::iostream: - S += "std::basic_iostream >"; - break; - } - } -}; - -class SpecialSubstitution final : public Node { -public: - SpecialSubKind SSK; - - SpecialSubstitution(SpecialSubKind SSK_) - : Node(KSpecialSubstitution), SSK(SSK_) {} - - StringView getBaseName() const override { - switch (SSK) { - case SpecialSubKind::allocator: - return StringView("allocator"); - case SpecialSubKind::basic_string: - return StringView("basic_string"); - case SpecialSubKind::string: - return StringView("string"); - case SpecialSubKind::istream: - return StringView("istream"); - case SpecialSubKind::ostream: - return StringView("ostream"); - case SpecialSubKind::iostream: - return StringView("iostream"); - } - LLVM_BUILTIN_UNREACHABLE; - } - - void printLeft(OutputStream &S) const override { - switch (SSK) { - case SpecialSubKind::allocator: - S += "std::allocator"; - break; - case SpecialSubKind::basic_string: - S += "std::basic_string"; - break; - case SpecialSubKind::string: - S += "std::string"; - break; - case SpecialSubKind::istream: - S += "std::istream"; - break; - case SpecialSubKind::ostream: - S += "std::ostream"; - break; - case SpecialSubKind::iostream: - S += "std::iostream"; - break; - } - } -}; - -class CtorDtorName final : public Node { - const Node *Basename; - const bool IsDtor; - -public: - CtorDtorName(Node *Basename_, bool IsDtor_) - : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {} - - void printLeft(OutputStream &S) const override { - if (IsDtor) - S += "~"; - S += Basename->getBaseName(); - } -}; - -class DtorName : public Node { - const Node *Base; - -public: - DtorName(Node *Base_) : Node(KDtorName), Base(Base_) {} - - void printLeft(OutputStream &S) const override { - S += "~"; - Base->printLeft(S); - } -}; - -class UnnamedTypeName : public Node { - const StringView Count; - -public: - UnnamedTypeName(StringView Count_) : Node(KUnnamedTypeName), Count(Count_) {} - - void printLeft(OutputStream &S) const override { - S += "'unnamed"; - S += Count; - S += "\'"; - } -}; - -class ClosureTypeName : public Node { - NodeArray Params; - StringView Count; - -public: - ClosureTypeName(NodeArray Params_, StringView Count_) - : Node(KClosureTypeName), Params(Params_), Count(Count_) {} - - void printLeft(OutputStream &S) const override { - S += "\'lambda"; - S += Count; - S += "\'("; - Params.printWithComma(S); - S += ")"; - } -}; - -class StructuredBindingName : public Node { - NodeArray Bindings; -public: - StructuredBindingName(NodeArray Bindings_) - : Node(KStructuredBindingName), Bindings(Bindings_) {} - - void printLeft(OutputStream &S) const override { - S += '['; - Bindings.printWithComma(S); - S += ']'; - } -}; - -// -- Expression Nodes -- - -struct Expr : public Node { - Expr(Kind K = KExpr) : Node(K) {} -}; - -class BinaryExpr : public Expr { - const Node *LHS; - const StringView InfixOperator; - const Node *RHS; - -public: - BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_) - : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {} - - void printLeft(OutputStream &S) const override { - // might be a template argument expression, then we need to disambiguate - // with parens. - if (InfixOperator == ">") - S += "("; - - S += "("; - LHS->print(S); - S += ") "; - S += InfixOperator; - S += " ("; - RHS->print(S); - S += ")"; - - if (InfixOperator == ">") - S += ")"; - } -}; - -class ArraySubscriptExpr : public Expr { - const Node *Op1; - const Node *Op2; - -public: - ArraySubscriptExpr(Node *Op1_, Node *Op2_) : Op1(Op1_), Op2(Op2_) {} - - void printLeft(OutputStream &S) const override { - S += "("; - Op1->print(S); - S += ")["; - Op2->print(S); - S += "]"; - } -}; - -class PostfixExpr : public Expr { - const Node *Child; - const StringView Operand; - -public: - PostfixExpr(Node *Child_, StringView Operand_) - : Child(Child_), Operand(Operand_) {} - - void printLeft(OutputStream &S) const override { - S += "("; - Child->print(S); - S += ")"; - S += Operand; - } -}; - -class ConditionalExpr : public Expr { - const Node *Cond; - const Node *Then; - const Node *Else; - -public: - ConditionalExpr(Node *Cond_, Node *Then_, Node *Else_) - : Cond(Cond_), Then(Then_), Else(Else_) {} - - void printLeft(OutputStream &S) const override { - S += "("; - Cond->print(S); - S += ") ? ("; - Then->print(S); - S += ") : ("; - Else->print(S); - S += ")"; - } -}; - -class MemberExpr : public Expr { - const Node *LHS; - const StringView Kind; - const Node *RHS; - -public: - MemberExpr(Node *LHS_, StringView Kind_, Node *RHS_) - : LHS(LHS_), Kind(Kind_), RHS(RHS_) {} - - void printLeft(OutputStream &S) const override { - LHS->print(S); - S += Kind; - RHS->print(S); - } -}; - -class EnclosingExpr : public Expr { - const StringView Prefix; - const Node *Infix; - const StringView Postfix; - -public: - EnclosingExpr(StringView Prefix_, Node *Infix_, StringView Postfix_) - : Prefix(Prefix_), Infix(Infix_), Postfix(Postfix_) {} - - void printLeft(OutputStream &S) const override { - S += Prefix; - Infix->print(S); - S += Postfix; - } -}; - -class CastExpr : public Expr { - // cast_kind(from) - const StringView CastKind; - const Node *To; - const Node *From; - -public: - CastExpr(StringView CastKind_, Node *To_, Node *From_) - : CastKind(CastKind_), To(To_), From(From_) {} - - void printLeft(OutputStream &S) const override { - S += CastKind; - S += "<"; - To->printLeft(S); - S += ">("; - From->printLeft(S); - S += ")"; - } -}; - -class SizeofParamPackExpr : public Expr { - Node *Pack; - -public: - SizeofParamPackExpr(Node *Pack_) : Pack(Pack_) {} - - void printLeft(OutputStream &S) const override { - S += "sizeof...("; - ParameterPackExpansion PPE(Pack); - PPE.printLeft(S); - S += ")"; - } -}; - -class CallExpr : public Expr { - const Node *Callee; - NodeArray Args; - -public: - CallExpr(Node *Callee_, NodeArray Args_) : Callee(Callee_), Args(Args_) {} - - void printLeft(OutputStream &S) const override { - Callee->print(S); - S += "("; - Args.printWithComma(S); - S += ")"; - } -}; - -class NewExpr : public Expr { - // new (expr_list) type(init_list) - NodeArray ExprList; - Node *Type; - NodeArray InitList; - bool IsGlobal; // ::operator new ? - bool IsArray; // new[] ? -public: - NewExpr(NodeArray ExprList_, Node *Type_, NodeArray InitList_, bool IsGlobal_, - bool IsArray_) - : ExprList(ExprList_), Type(Type_), InitList(InitList_), - IsGlobal(IsGlobal_), IsArray(IsArray_) {} - - void printLeft(OutputStream &S) const override { - if (IsGlobal) - S += "::operator "; - S += "new"; - if (IsArray) - S += "[]"; - S += ' '; - if (!ExprList.empty()) { - S += "("; - ExprList.printWithComma(S); - S += ")"; - } - Type->print(S); - if (!InitList.empty()) { - S += "("; - InitList.printWithComma(S); - S += ")"; - } - - } -}; - -class DeleteExpr : public Expr { - Node *Op; - bool IsGlobal; - bool IsArray; - -public: - DeleteExpr(Node *Op_, bool IsGlobal_, bool IsArray_) - : Op(Op_), IsGlobal(IsGlobal_), IsArray(IsArray_) {} - - void printLeft(OutputStream &S) const override { - if (IsGlobal) - S += "::"; - S += "delete"; - if (IsArray) - S += "[] "; - Op->print(S); - } -}; - -class PrefixExpr : public Expr { - StringView Prefix; - Node *Child; - -public: - PrefixExpr(StringView Prefix_, Node *Child_) : Prefix(Prefix_), Child(Child_) {} - - void printLeft(OutputStream &S) const override { - S += Prefix; - S += "("; - Child->print(S); - S += ")"; - } -}; - -class FunctionParam : public Expr { - StringView Number; - -public: - FunctionParam(StringView Number_) : Number(Number_) {} - - void printLeft(OutputStream &S) const override { - S += "fp"; - S += Number; - } -}; - -class ConversionExpr : public Expr { - const Node *Type; - NodeArray Expressions; - -public: - ConversionExpr(const Node *Type_, NodeArray Expressions_) - : Type(Type_), Expressions(Expressions_) {} - - void printLeft(OutputStream &S) const override { - S += "("; - Type->print(S); - S += ")("; - Expressions.printWithComma(S); - S += ")"; - } -}; - -class InitListExpr : public Expr { - Node *Ty; - NodeArray Inits; -public: - InitListExpr(Node *Ty_, NodeArray Inits_) : Ty(Ty_), Inits(Inits_) {} - - void printLeft(OutputStream &S) const override { - if (Ty) - Ty->print(S); - S += '{'; - Inits.printWithComma(S); - S += '}'; - } -}; - -class BracedExpr : public Expr { - Node *Elem; - Node *Init; - bool IsArray; -public: - BracedExpr(Node *Elem_, Node *Init_, bool IsArray_) - : Expr(KBracedExpr), Elem(Elem_), Init(Init_), IsArray(IsArray_) {} - - void printLeft(OutputStream &S) const override { - if (IsArray) { - S += '['; - Elem->print(S); - S += ']'; - } else { - S += '.'; - Elem->print(S); - } - if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr) - S += " = "; - Init->print(S); - } -}; - -class BracedRangeExpr : public Expr { - Node *First; - Node *Last; - Node *Init; -public: - BracedRangeExpr(Node *First_, Node *Last_, Node *Init_) - : Expr(KBracedRangeExpr), First(First_), Last(Last_), Init(Init_) {} - - void printLeft(OutputStream &S) const override { - S += '['; - First->print(S); - S += " ... "; - Last->print(S); - S += ']'; - if (Init->getKind() != KBracedExpr && Init->getKind() != KBracedRangeExpr) - S += " = "; - Init->print(S); - } -}; - -struct FoldExpr : Expr { - Node *Pack, *Init; - StringView OperatorName; - bool IsLeftFold; - - FoldExpr(bool IsLeftFold_, StringView OperatorName_, Node *Pack_, Node *Init_) - : Pack(Pack_), Init(Init_), OperatorName(OperatorName_), - IsLeftFold(IsLeftFold_) {} - - void printLeft(OutputStream &S) const override { - auto PrintPack = [&] { - S += '('; - ParameterPackExpansion(Pack).print(S); - S += ')'; + void print(NodeOrString NS) { + if (NS.isNode()) + print(NS.asNode()); + else if (NS.isString()) + print(NS.asString()); + else + printStr("NodeOrString()"); + } + void print(NodeArray A) { + ++Depth; + printStr("{"); + bool First = true; + for (const Node *N : A) { + if (First) + print(N); + else + printWithComma(N); + First = false; + } + printStr("}"); + --Depth; + } + // Overload used when T is exactly 'bool', not merely convertible to 'bool'. + template + void print(T B) { + printStr(B ? "true" : "false"); + } + void print(size_t N) { + fprintf(stderr, "%zu", N); + } + void print(ReferenceKind RK) { + switch (RK) { + case ReferenceKind::LValue: + return printStr("ReferenceKind::LValue"); + case ReferenceKind::RValue: + return printStr("ReferenceKind::RValue"); + } + } + void print(FunctionRefQual RQ) { + switch (RQ) { + case FunctionRefQual::FrefQualNone: + return printStr("FunctionRefQual::FrefQualNone"); + case FunctionRefQual::FrefQualLValue: + return printStr("FunctionRefQual::FrefQualLValue"); + case FunctionRefQual::FrefQualRValue: + return printStr("FunctionRefQual::FrefQualRValue"); + } + } + void print(Qualifiers Qs) { + if (!Qs) return printStr("QualNone"); + struct QualName { Qualifiers Q; const char *Name; } Names[] = { + {QualConst, "QualConst"}, + {QualVolatile, "QualVolatile"}, + {QualRestrict, "QualRestrict"}, }; - - S += '('; - - if (IsLeftFold) { - // init op ... op pack - if (Init != nullptr) { - Init->print(S); - S += ' '; - S += OperatorName; - S += ' '; - } - // ... op pack - S += "... "; - S += OperatorName; - S += ' '; - PrintPack(); - } else { // !IsLeftFold - // pack op ... - PrintPack(); - S += ' '; - S += OperatorName; - S += " ..."; - // pack op ... op init - if (Init != nullptr) { - S += ' '; - S += OperatorName; - S += ' '; - Init->print(S); + for (QualName Name : Names) { + if (Qs & Name.Q) { + printStr(Name.Name); + Qs = Qualifiers(Qs & ~Name.Q); + if (Qs) printStr(" | "); } } - S += ')'; } -}; - -class ThrowExpr : public Expr { - const Node *Op; - -public: - ThrowExpr(Node *Op_) : Op(Op_) {} - - void printLeft(OutputStream &S) const override { - S += "throw "; - Op->print(S); + void print(SpecialSubKind SSK) { + switch (SSK) { + case SpecialSubKind::allocator: + return printStr("SpecialSubKind::allocator"); + case SpecialSubKind::basic_string: + return printStr("SpecialSubKind::basic_string"); + case SpecialSubKind::string: + return printStr("SpecialSubKind::string"); + case SpecialSubKind::istream: + return printStr("SpecialSubKind::istream"); + case SpecialSubKind::ostream: + return printStr("SpecialSubKind::ostream"); + case SpecialSubKind::iostream: + return printStr("SpecialSubKind::iostream"); + } } -}; -class BoolExpr : public Expr { - bool Value; - -public: - BoolExpr(bool Value_) : Value(Value_) {} - - void printLeft(OutputStream &S) const override { - S += Value ? StringView("true") : StringView("false"); + void newLine() { + printStr("\n"); + for (unsigned I = 0; I != Depth; ++I) + printStr(" "); + PendingNewline = false; } -}; -class IntegerCastExpr : public Expr { - // ty(integer) - Node *Ty; - StringView Integer; + template void printWithPendingNewline(T V) { + print(V); + if (wantsNewline(V)) + PendingNewline = true; + } -public: - IntegerCastExpr(Node *Ty_, StringView Integer_) - : Ty(Ty_), Integer(Integer_) {} + template void printWithComma(T V) { + if (PendingNewline || wantsNewline(V)) { + printStr(","); + newLine(); + } else { + printStr(", "); + } - void printLeft(OutputStream &S) const override { - S += "("; - Ty->print(S); - S += ")"; - S += Integer; + printWithPendingNewline(V); } -}; -class IntegerExpr : public Expr { - StringView Type; - StringView Value; + struct CtorArgPrinter { + DumpVisitor &Visitor; -public: - IntegerExpr(StringView Type_, StringView Value_) : Type(Type_), Value(Value_) {} - - void printLeft(OutputStream &S) const override { - if (Type.size() > 3) { - S += "("; - S += Type; - S += ")"; + template void operator()(T V, Rest ...Vs) { + if (Visitor.anyWantNewline(V, Vs...)) + Visitor.newLine(); + Visitor.printWithPendingNewline(V); + int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 }; + (void)PrintInOrder; } + }; + + template void operator()(const NodeT *Node) { + Depth += 2; + fprintf(stderr, "%s(", llvm::itanium_demangle::NodeKind::name()); + Node->match(CtorArgPrinter{*this}); + fprintf(stderr, ")"); + Depth -= 2; + } - if (Value[0] == 'n') { - S += "-"; - S += Value.dropFront(1); - } else - S += Value; - - if (Type.size() <= 3) - S += Type; + void operator()(const ForwardTemplateReference *Node) { + Depth += 2; + fprintf(stderr, "ForwardTemplateReference("); + if (Node->Ref && !Node->Printing) { + Node->Printing = true; + CtorArgPrinter{*this}(Node->Ref); + Node->Printing = false; + } else { + CtorArgPrinter{*this}(Node->Index); + } + fprintf(stderr, ")"); + Depth -= 2; } }; -template struct FloatData; - -template class FloatExpr : public Expr { - const StringView Contents; - -public: - FloatExpr(StringView Contents_) : Contents(Contents_) {} - - void printLeft(OutputStream &s) const override { - const char *first = Contents.begin(); - const char *last = Contents.end() + 1; - - const size_t N = FloatData::mangled_size; - if (static_cast(last - first) > N) { - last = first + N; - union { - Float value; - char buf[sizeof(Float)]; - }; - const char *t = first; - char *e = buf; - for (; t != last; ++t, ++e) { - unsigned d1 = isdigit(*t) ? static_cast(*t - '0') - : static_cast(*t - 'a' + 10); - ++t; - unsigned d0 = isdigit(*t) ? static_cast(*t - '0') - : static_cast(*t - 'a' + 10); - *e = static_cast((d1 << 4) + d0); - } -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::reverse(buf, e); +void llvm::itanium_demangle::Node::dump() const { + DumpVisitor V; + visit(std::ref(V)); + V.newLine(); +} #endif - char num[FloatData::max_demangled_size] = {0}; - int n = snprintf(num, sizeof(num), FloatData::spec, value); - s += StringView(num, num + n); - } - } -}; +//===----------------------------------------------------------------------===// +// Code beyond this point should not be synchronized with libc++abi. +//===----------------------------------------------------------------------===// + +namespace { class BumpPointerAllocator { struct BlockMeta { BlockMeta* Next; @@ -1823,125 +295,6 @@ ~BumpPointerAllocator() { reset(); } }; -template -class PODSmallVector { - static_assert(std::is_pod::value, - "T is required to be a plain old data type"); - - T* First; - T* Last; - T* Cap; - T Inline[N]; - - bool isInline() const { return First == Inline; } - - void clearInline() { - First = Inline; - Last = Inline; - Cap = Inline + N; - } - - void reserve(size_t NewCap) { - size_t S = size(); - if (isInline()) { - auto* Tmp = static_cast(std::malloc(NewCap * sizeof(T))); - if (Tmp == nullptr) - std::terminate(); - std::copy(First, Last, Tmp); - First = Tmp; - } else { - First = static_cast(std::realloc(First, NewCap * sizeof(T))); - if (First == nullptr) - std::terminate(); - } - Last = First + S; - Cap = First + NewCap; - } - -public: - PODSmallVector() : First(Inline), Last(First), Cap(Inline + N) {} - - PODSmallVector(const PODSmallVector&) = delete; - PODSmallVector& operator=(const PODSmallVector&) = delete; - - PODSmallVector(PODSmallVector&& Other) : PODSmallVector() { - if (Other.isInline()) { - std::copy(Other.begin(), Other.end(), First); - Last = First + Other.size(); - Other.clear(); - return; - } - - First = Other.First; - Last = Other.Last; - Cap = Other.Cap; - Other.clearInline(); - } - - PODSmallVector& operator=(PODSmallVector&& Other) { - if (Other.isInline()) { - if (!isInline()) { - std::free(First); - clearInline(); - } - std::copy(Other.begin(), Other.end(), First); - Last = First + Other.size(); - Other.clear(); - return *this; - } - - if (isInline()) { - First = Other.First; - Last = Other.Last; - Cap = Other.Cap; - Other.clearInline(); - return *this; - } - - std::swap(First, Other.First); - std::swap(Last, Other.Last); - std::swap(Cap, Other.Cap); - Other.clear(); - return *this; - } - - void push_back(const T& Elem) { - if (Last == Cap) - reserve(size() * 2); - *Last++ = Elem; - } - - void pop_back() { - assert(Last != First && "Popping empty vector!"); - --Last; - } - - void dropBack(size_t Index) { - assert(Index <= size() && "dropBack() can't expand!"); - Last = First + Index; - } - - T* begin() { return First; } - T* end() { return Last; } - - bool empty() const { return First == Last; } - size_t size() const { return static_cast(Last - First); } - T& back() { - assert(Last != First && "Calling back() on empty vector!"); - return *(Last - 1); - } - T& operator[](size_t Index) { - assert(Index < size() && "Invalid access!"); - return *(begin() + Index); - } - void clear() { Last = First; } - - ~PODSmallVector() { - if (!isInline()) - std::free(First); - } -}; - class DefaultAllocator { BumpPointerAllocator Alloc; @@ -1958,3013 +311,6 @@ } }; -template -struct Db { - const char *First; - const char *Last; - - // Name stack, this is used by the parser to hold temporary names that were - // parsed. The parser collapses multiple names into new nodes to construct - // the AST. Once the parser is finished, names.size() == 1. - PODSmallVector Names; - - // Substitution table. Itanium supports name substitutions as a means of - // compression. The string "S42_" refers to the 44nd entry (base-36) in this - // table. - PODSmallVector Subs; - - // Template parameter table. Like the above, but referenced like "T42_". - // This has a smaller size compared to Subs and Names because it can be - // stored on the stack. - PODSmallVector TemplateParams; - - // Set of unresolved forward references. These can occur in a - // conversion operator's type, and are resolved in the enclosing . - PODSmallVector ForwardTemplateRefs; - - void (*TypeCallback)(void *, const char *) = nullptr; - void *TypeCallbackContext = nullptr; - - bool TryToParseTemplateArgs = true; - bool PermitForwardTemplateReferences = false; - bool ParsingLambdaParams = false; - - Alloc ASTAllocator; - - Db(const char *First_, const char *Last_) : First(First_), Last(Last_) {} - - void reset(const char *First_, const char *Last_) { - First = First_; - Last = Last_; - Names.clear(); - Subs.clear(); - TemplateParams.clear(); - ParsingLambdaParams = false; - TryToParseTemplateArgs = true; - PermitForwardTemplateReferences = false; - ASTAllocator.reset(); - } - - template T *make(Args &&... args) { - return ASTAllocator.template makeNode(std::forward(args)...); - } - - template NodeArray makeNodeArray(It begin, It end) { - size_t sz = static_cast(end - begin); - void *mem = ASTAllocator.allocateNodeArray(sz); - Node **data = new (mem) Node *[sz]; - std::copy(begin, end, data); - return NodeArray(data, sz); - } - - NodeArray popTrailingNodeArray(size_t FromPosition) { - assert(FromPosition <= Names.size()); - NodeArray res = - makeNodeArray(Names.begin() + (long)FromPosition, Names.end()); - Names.dropBack(FromPosition); - return res; - } - - bool consumeIf(StringView S) { - if (StringView(First, Last).startsWith(S)) { - First += S.size(); - return true; - } - return false; - } - - bool consumeIf(char C) { - if (First != Last && *First == C) { - ++First; - return true; - } - return false; - } - - char consume() { return First != Last ? *First++ : '\0'; } - - char look(unsigned Lookahead = 0) { - if (static_cast(Last - First) <= Lookahead) - return '\0'; - return First[Lookahead]; - } - - size_t numLeft() const { return static_cast(Last - First); } - - StringView parseNumber(bool AllowNegative = false); - Qualifiers parseCVQualifiers(); - bool parsePositiveInteger(size_t *Out); - StringView parseBareSourceName(); - - bool parseSeqId(size_t *Out); - Node *parseSubstitution(); - Node *parseTemplateParam(); - Node *parseTemplateArgs(bool TagTemplates = false); - Node *parseTemplateArg(); - - /// Parse the production. - Node *parseExpr(); - Node *parsePrefixExpr(StringView Kind); - Node *parseBinaryExpr(StringView Kind); - Node *parseIntegerLiteral(StringView Lit); - Node *parseExprPrimary(); - template Node *parseFloatingLiteral(); - Node *parseFunctionParam(); - Node *parseNewExpr(); - Node *parseConversionExpr(); - Node *parseBracedExpr(); - Node *parseFoldExpr(); - - /// Parse the production. - Node *parseType(); - Node *parseFunctionType(); - Node *parseVectorType(); - Node *parseDecltype(); - Node *parseArrayType(); - Node *parsePointerToMemberType(); - Node *parseClassEnumType(); - Node *parseQualifiedType(); - - Node *parseEncoding(); - bool parseCallOffset(); - Node *parseSpecialName(); - - /// Holds some extra information about a that is being parsed. This - /// information is only pertinent if the refers to an . - struct NameState { - bool CtorDtorConversion = false; - bool EndsWithTemplateArgs = false; - Qualifiers CVQualifiers = QualNone; - FunctionRefQual ReferenceQualifier = FrefQualNone; - size_t ForwardTemplateRefsBegin; - - NameState(Db *Enclosing) - : ForwardTemplateRefsBegin(Enclosing->ForwardTemplateRefs.size()) {} - }; - - bool resolveForwardTemplateRefs(NameState &State) { - size_t I = State.ForwardTemplateRefsBegin; - size_t E = ForwardTemplateRefs.size(); - for (; I < E; ++I) { - size_t Idx = ForwardTemplateRefs[I]->Index; - if (Idx >= TemplateParams.size()) - return true; - ForwardTemplateRefs[I]->Ref = TemplateParams[Idx]; - } - ForwardTemplateRefs.dropBack(State.ForwardTemplateRefsBegin); - return false; - } - - /// Parse the production> - Node *parseName(NameState *State = nullptr); - Node *parseLocalName(NameState *State); - Node *parseOperatorName(NameState *State); - Node *parseUnqualifiedName(NameState *State); - Node *parseUnnamedTypeName(NameState *State); - Node *parseSourceName(NameState *State); - Node *parseUnscopedName(NameState *State); - Node *parseNestedName(NameState *State); - Node *parseCtorDtorName(Node *&SoFar, NameState *State); - - Node *parseAbiTags(Node *N); - - /// Parse the production. - Node *parseUnresolvedName(); - Node *parseSimpleId(); - Node *parseBaseUnresolvedName(); - Node *parseUnresolvedType(); - Node *parseDestructorName(); - - /// Top-level entry point into the parser. - Node *parse(); -}; - -const char* parse_discriminator(const char* first, const char* last); - -// ::= // N -// ::= # See Scope Encoding below // Z -// ::= -// ::= -// -// ::= -// ::= -template Node *Db::parseName(NameState *State) { - consumeIf('L'); // extension - - if (look() == 'N') - return parseNestedName(State); - if (look() == 'Z') - return parseLocalName(State); - - // ::= - if (look() == 'S' && look(1) != 't') { - Node *S = parseSubstitution(); - if (S == nullptr) - return nullptr; - if (look() != 'I') - return nullptr; - Node *TA = parseTemplateArgs(State != nullptr); - if (TA == nullptr) - return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(S, TA); - } - - Node *N = parseUnscopedName(State); - if (N == nullptr) - return nullptr; - // ::= - if (look() == 'I') { - Subs.push_back(N); - Node *TA = parseTemplateArgs(State != nullptr); - if (TA == nullptr) - return nullptr; - if (State) State->EndsWithTemplateArgs = true; - return make(N, TA); - } - // ::= - return N; -} - -// := Z E [] -// := Z E s [] -// := Z Ed [ ] _ -template Node *Db::parseLocalName(NameState *State) { - if (!consumeIf('Z')) - return nullptr; - Node *Encoding = parseEncoding(); - if (Encoding == nullptr || !consumeIf('E')) - return nullptr; - - if (consumeIf('s')) { - First = parse_discriminator(First, Last); - return make(Encoding, make("string literal")); - } - - if (consumeIf('d')) { - parseNumber(true); - if (!consumeIf('_')) - return nullptr; - Node *N = parseName(State); - if (N == nullptr) - return nullptr; - return make(Encoding, N); - } - - Node *Entity = parseName(State); - if (Entity == nullptr) - return nullptr; - First = parse_discriminator(First, Last); - return make(Encoding, Entity); -} - -// ::= -// ::= St # ::std:: -// extension ::= StL -template Node *Db::parseUnscopedName(NameState *State) { - if (consumeIf("StL") || consumeIf("St")) { - Node *R = parseUnqualifiedName(State); - if (R == nullptr) - return nullptr; - return make(R); - } - return parseUnqualifiedName(State); -} - -// ::= [abi-tags] -// ::= -// ::= -// ::= -// ::= DC + E # structured binding declaration -template -Node *Db::parseUnqualifiedName(NameState *State) { - // s are special-cased in parseNestedName(). - Node *Result; - if (look() == 'U') - Result = parseUnnamedTypeName(State); - else if (look() >= '1' && look() <= '9') - Result = parseSourceName(State); - else if (consumeIf("DC")) { - size_t BindingsBegin = Names.size(); - do { - Node *Binding = parseSourceName(State); - if (Binding == nullptr) - return nullptr; - Names.push_back(Binding); - } while (!consumeIf('E')); - Result = make(popTrailingNodeArray(BindingsBegin)); - } else - Result = parseOperatorName(State); - if (Result != nullptr) - Result = parseAbiTags(Result); - return Result; -} - -// ::= Ut [] _ -// ::= -// -// ::= Ul E [ ] _ -// -// ::= + # Parameter types or "v" if the lambda has no parameters -template Node *Db::parseUnnamedTypeName(NameState *) { - if (consumeIf("Ut")) { - StringView Count = parseNumber(); - if (!consumeIf('_')) - return nullptr; - return make(Count); - } - if (consumeIf("Ul")) { - NodeArray Params; - SwapAndRestore SwapParams(ParsingLambdaParams, true); - if (!consumeIf("vE")) { - size_t ParamsBegin = Names.size(); - do { - Node *P = parseType(); - if (P == nullptr) - return nullptr; - Names.push_back(P); - } while (!consumeIf('E')); - Params = popTrailingNodeArray(ParamsBegin); - } - StringView Count = parseNumber(); - if (!consumeIf('_')) - return nullptr; - return make(Params, Count); - } - return nullptr; -} - -// ::= -template Node *Db::parseSourceName(NameState *) { - size_t Length = 0; - if (parsePositiveInteger(&Length)) - return nullptr; - if (numLeft() < Length || Length == 0) - return nullptr; - StringView Name(First, First + Length); - First += Length; - if (Name.startsWith("_GLOBAL__N")) - return make("(anonymous namespace)"); - return make(Name); -} - -// ::= aa # && -// ::= ad # & (unary) -// ::= an # & -// ::= aN # &= -// ::= aS # = -// ::= cl # () -// ::= cm # , -// ::= co # ~ -// ::= cv # (cast) -// ::= da # delete[] -// ::= de # * (unary) -// ::= dl # delete -// ::= dv # / -// ::= dV # /= -// ::= eo # ^ -// ::= eO # ^= -// ::= eq # == -// ::= ge # >= -// ::= gt # > -// ::= ix # [] -// ::= le # <= -// ::= li # operator "" -// ::= ls # << -// ::= lS # <<= -// ::= lt # < -// ::= mi # - -// ::= mI # -= -// ::= ml # * -// ::= mL # *= -// ::= mm # -- (postfix in context) -// ::= na # new[] -// ::= ne # != -// ::= ng # - (unary) -// ::= nt # ! -// ::= nw # new -// ::= oo # || -// ::= or # | -// ::= oR # |= -// ::= pm # ->* -// ::= pl # + -// ::= pL # += -// ::= pp # ++ (postfix in context) -// ::= ps # + (unary) -// ::= pt # -> -// ::= qu # ? -// ::= rm # % -// ::= rM # %= -// ::= rs # >> -// ::= rS # >>= -// ::= ss # <=> C++2a -// ::= v # vendor extended operator -template Node *Db::parseOperatorName(NameState *State) { - switch (look()) { - case 'a': - switch (look(1)) { - case 'a': - First += 2; - return make("operator&&"); - case 'd': - case 'n': - First += 2; - return make("operator&"); - case 'N': - First += 2; - return make("operator&="); - case 'S': - First += 2; - return make("operator="); - } - return nullptr; - case 'c': - switch (look(1)) { - case 'l': - First += 2; - return make("operator()"); - case 'm': - First += 2; - return make("operator,"); - case 'o': - First += 2; - return make("operator~"); - // ::= cv # (cast) - case 'v': { - First += 2; - SwapAndRestore SaveTemplate(TryToParseTemplateArgs, false); - // If we're parsing an encoding, State != nullptr and the conversion - // operators' could have a that refers to some - // s further ahead in the mangled name. - SwapAndRestore SavePermit(PermitForwardTemplateReferences, - PermitForwardTemplateReferences || - State != nullptr); - Node* Ty = parseType(); - if (Ty == nullptr) - return nullptr; - if (State) State->CtorDtorConversion = true; - return make(Ty); - } - } - return nullptr; - case 'd': - switch (look(1)) { - case 'a': - First += 2; - return make("operator delete[]"); - case 'e': - First += 2; - return make("operator*"); - case 'l': - First += 2; - return make("operator delete"); - case 'v': - First += 2; - return make("operator/"); - case 'V': - First += 2; - return make("operator/="); - } - return nullptr; - case 'e': - switch (look(1)) { - case 'o': - First += 2; - return make("operator^"); - case 'O': - First += 2; - return make("operator^="); - case 'q': - First += 2; - return make("operator=="); - } - return nullptr; - case 'g': - switch (look(1)) { - case 'e': - First += 2; - return make("operator>="); - case 't': - First += 2; - return make("operator>"); - } - return nullptr; - case 'i': - if (look(1) == 'x') { - First += 2; - return make("operator[]"); - } - return nullptr; - case 'l': - switch (look(1)) { - case 'e': - First += 2; - return make("operator<="); - // ::= li # operator "" - case 'i': { - First += 2; - Node *SN = parseSourceName(State); - if (SN == nullptr) - return nullptr; - return make(SN); - } - case 's': - First += 2; - return make("operator<<"); - case 'S': - First += 2; - return make("operator<<="); - case 't': - First += 2; - return make("operator<"); - } - return nullptr; - case 'm': - switch (look(1)) { - case 'i': - First += 2; - return make("operator-"); - case 'I': - First += 2; - return make("operator-="); - case 'l': - First += 2; - return make("operator*"); - case 'L': - First += 2; - return make("operator*="); - case 'm': - First += 2; - return make("operator--"); - } - return nullptr; - case 'n': - switch (look(1)) { - case 'a': - First += 2; - return make("operator new[]"); - case 'e': - First += 2; - return make("operator!="); - case 'g': - First += 2; - return make("operator-"); - case 't': - First += 2; - return make("operator!"); - case 'w': - First += 2; - return make("operator new"); - } - return nullptr; - case 'o': - switch (look(1)) { - case 'o': - First += 2; - return make("operator||"); - case 'r': - First += 2; - return make("operator|"); - case 'R': - First += 2; - return make("operator|="); - } - return nullptr; - case 'p': - switch (look(1)) { - case 'm': - First += 2; - return make("operator->*"); - case 'l': - First += 2; - return make("operator+"); - case 'L': - First += 2; - return make("operator+="); - case 'p': - First += 2; - return make("operator++"); - case 's': - First += 2; - return make("operator+"); - case 't': - First += 2; - return make("operator->"); - } - return nullptr; - case 'q': - if (look(1) == 'u') { - First += 2; - return make("operator?"); - } - return nullptr; - case 'r': - switch (look(1)) { - case 'm': - First += 2; - return make("operator%"); - case 'M': - First += 2; - return make("operator%="); - case 's': - First += 2; - return make("operator>>"); - case 'S': - First += 2; - return make("operator>>="); - } - return nullptr; - case 's': - if (look(1) == 's') { - First += 2; - return make("operator<=>"); - } - return nullptr; - // ::= v # vendor extended operator - case 'v': - if (std::isdigit(look(1))) { - First += 2; - Node *SN = parseSourceName(State); - if (SN == nullptr) - return nullptr; - return make(SN); - } - return nullptr; - } - return nullptr; -} - -// ::= C1 # complete object constructor -// ::= C2 # base object constructor -// ::= C3 # complete object allocating constructor -// extension ::= C5 # ? -// ::= D0 # deleting destructor -// ::= D1 # complete object destructor -// ::= D2 # base object destructor -// extension ::= D5 # ? -template -Node *Db::parseCtorDtorName(Node *&SoFar, NameState *State) { - if (SoFar->K == Node::KSpecialSubstitution) { - auto SSK = static_cast(SoFar)->SSK; - switch (SSK) { - case SpecialSubKind::string: - case SpecialSubKind::istream: - case SpecialSubKind::ostream: - case SpecialSubKind::iostream: - SoFar = make(SSK); - default: - break; - } - } - - if (consumeIf('C')) { - bool IsInherited = consumeIf('I'); - if (look() != '1' && look() != '2' && look() != '3' && look() != '5') - return nullptr; - ++First; - if (State) State->CtorDtorConversion = true; - if (IsInherited) { - if (parseName(State) == nullptr) - return nullptr; - } - return make(SoFar, false); - } - - if (look() == 'D' && - (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) { - First += 2; - if (State) State->CtorDtorConversion = true; - return make(SoFar, true); - } - - return nullptr; -} - -// ::= N [] [] E -// ::= N [] [] E -// -// ::= -// ::= -// ::= -// ::= -// ::= # empty -// ::= -// ::= -// extension ::= L -// -// := [] M -// -// ::=