Index: include/llvm/Demangle/Demangle.h =================================================================== --- include/llvm/Demangle/Demangle.h +++ include/llvm/Demangle/Demangle.h @@ -85,6 +85,8 @@ /// generated by the implementation, such as vtables and typeinfo names. bool isSpecialName() const; + char *mangle(char *Buf, size_t *N) const; + ~ItaniumPartialDemangler(); private: void *RootNode; Index: lib/Demangle/ItaniumDemangle.cpp =================================================================== --- lib/Demangle/ItaniumDemangle.cpp +++ lib/Demangle/ItaniumDemangle.cpp @@ -24,6 +24,7 @@ #include #include #include +#include namespace { // Base class of all AST nodes. The AST is built by the parser, then is @@ -31,7 +32,6 @@ class Node { public: enum Kind : unsigned char { - KNodeArrayNode, KDotSuffix, KVendorExtQualType, KQualType, @@ -39,7 +39,10 @@ KPostfixQualifiedType, KElaboratedTypeSpefType, KNameType, + KOperatorName, + KBuiltinType, KAbiTagAttr, + KDefaultArg, KEnableIfAttr, KObjCProtoName, KPointerType, @@ -52,19 +55,24 @@ KFunctionEncoding, KLiteralOperator, KSpecialName, + KSpecialNameX, KCtorVtableSpecialName, KQualifiedName, KNestedName, + KFullNestedName, KLocalName, KVectorType, KParameterPack, KTemplateArgumentPack, KParameterPackExpansion, KTemplateArgs, + KTemplateExpression, KForwardTemplateReference, KNameWithTemplateArgs, KGlobalQualifiedName, KStdQualifiedName, + KStdName, + KSubstitution, KExpandedSpecialSubstitution, KSpecialSubstitution, KCtorDtorName, @@ -73,8 +81,14 @@ KClosureTypeName, KStructuredBindingName, KExpr, + KBinaryExpr, KBracedExpr, KBracedRangeExpr, + KEnclosingExprX, + KFunctionParam, + KIntegerExpr, + KSizeofAliasParamPackExpr, + KSizeofParamPackExpr, }; Kind K; @@ -200,19 +214,11 @@ } }; -struct NodeArrayNode : Node { - NodeArray Array; - NodeArrayNode(NodeArray Array_) : Node(KNodeArrayNode), Array(Array_) {} - void printLeft(OutputStream &S) const override { - Array.printWithComma(S); - } -}; - class DotSuffix final : public Node { +public: const Node *Prefix; const StringView Suffix; -public: DotSuffix(Node *Prefix_, StringView Suffix_) : Node(KDotSuffix), Prefix(Prefix_), Suffix(Suffix_) {} @@ -225,10 +231,10 @@ }; class VendorExtQualType final : public Node { +public: const Node *Ty; StringView Ext; -public: VendorExtQualType(Node *Ty_, StringView Ext_) : Node(KVendorExtQualType), Ty(Ty_), Ext(Ext_) {} @@ -258,9 +264,6 @@ class QualType : public Node { protected: - const Qualifiers Quals; - const Node *Child; - void printQuals(OutputStream &S) const { if (Quals & QualConst) S += " const"; @@ -271,6 +274,9 @@ } public: + const Qualifiers Quals; + const Node *Child; + QualType(Node *Child_, Qualifiers Quals_) : Node(KQualType, Child_->RHSComponentCache, Child_->ArrayCache, Child_->FunctionCache), @@ -295,9 +301,9 @@ }; class ConversionOperatorType final : public Node { +public: const Node *Ty; -public: ConversionOperatorType(Node *Ty_) : Node(KConversionOperatorType), Ty(Ty_) {} @@ -308,23 +314,26 @@ }; class PostfixQualifiedType final : public Node { +public: + enum Kind { KComplex, KImaginary }; + const Node *Ty; - const StringView Postfix; + const Kind K; -public: - PostfixQualifiedType(Node *Ty_, StringView Postfix_) - : Node(KPostfixQualifiedType), Ty(Ty_), Postfix(Postfix_) {} + PostfixQualifiedType(Node *Ty_, Kind K_) + : Node(KPostfixQualifiedType), Ty(Ty_), K(K_) {} void printLeft(OutputStream &s) const override { + static constexpr const char *Postfix[] = {" complex", " imaginary"}; Ty->printLeft(s); - s += Postfix; + s += Postfix[K]; } }; class NameType final : public Node { +public: const StringView Name; -public: NameType(StringView Name_) : Node(KNameType), Name(Name_) {} StringView getName() const { return Name; } @@ -333,16 +342,233 @@ void printLeft(OutputStream &s) const override { s += Name; } }; +class OperatorName final : public Node { +public: + enum Kind { + Oamp_amp, + Oamp1, + Oamp, + Oamp_eq, + Oeq, + Ocall, + Ocomma, + Otilde, + Odel_arr, + Oderef, + Odel, + Oslash, + Oslash_eq, + Ocaret, + Ocaret_eq, + Oeq_eq, + Ogt_eq, + Ogt, + Oindex, + Olt_eq, + Olt_lt, + Olt_lt_eq, + Olt, + Osub, + Osub_eq, + Omul, + Omul_eq, + Osub_sub, + Onew_arr, + Onot_eq, + Oneg, + Onot, + Onew, + Oor_or, + Oor, + Oor_eq, + Oarrow_mul, + Oplus, + Oplus_eq, + Oplus_plus, + Oplus1, + Oarrow, + Oternary, + Omod, + Omod_eq, + Ogt_gt, + Ogt_gt_eq, + Olt_eq_gt, + }; + + Kind K; + +public: + OperatorName(Kind K_) : Node(KOperatorName), K(K_) {} + + StringView getName() const { + static constexpr const char *OpStr[] = { + "operator&&", "operator&", "operator&", "operator&=", + "operator=", "operator()", "operator,", "operator~", + "operator delete[]", "operator*", "operator delete", "operator/", + "operator/=", "operator^", "operator^=", "operator==", + "operator>=", "operator>", "operator[]", "operator<=", + "operator<<", "operator<<=", "operator<", "operator-", + "operator-=", "operator*", "operator*=", "operator--", + "operator new[]", "operator!=", "operator-", "operator!", + "operator new", "operator||", "operator|", "operator|=", + "operator->*", "operator+", "operator+=", "operator++", + "operator+", "operator->", "operator?", "operator%", + "operator%=", "operator>>", "operator>>=", "operator<=>", + }; + return OpStr[K]; + } + StringView getBaseName() const override { return getName(); } + void printLeft(OutputStream &S) const override { S += getName(); } +}; + +class BuiltinType final : public Node { +public: + enum Kind { + Kvoid, + Kwchar_t, + Kbool, + Kchar, + Ksigned_char, + Kunsigned_char, + Kshort, + Kunsigned_short, + Kint, + Kunsigned_int, + Klong, + Kunsigned_long, + Klong_long, + Kunsigned_long_long, + K__int128, + Kunsigned__int128, + Kfloat, + Kdouble, + Klong_double, + K__float128, + Kellipsis, + Kdecimal64, + Kdecimal128, + Kdecimal32, + Kdecimal16, + Kchar32_t, + Kchar16_t, + Kauto, + Kdecltype_auto, + Knullptr_t, + }; + + const Kind K; + + BuiltinType(Kind K_) : Node(KBuiltinType), K(K_) {} + + void printLeft(OutputStream &S) const override { + switch (K) { + case Kvoid: + S += "void"; + return; + case Kwchar_t: + S += "wchar_t"; + return; + case Kbool: + S += "bool"; + return; + case Kchar: + S += "char"; + return; + case Ksigned_char: + S += "signed char"; + return; + case Kunsigned_char: + S += "unsigned char"; + return; + case Kshort: + S += "short"; + return; + case Kunsigned_short: + S += "unsigned short"; + return; + case Kint: + S += "int"; + return; + case Kunsigned_int: + S += "unsigned int"; + return; + case Klong: + S += "long"; + return; + case Kunsigned_long: + S += "unsigned long"; + return; + case Klong_long: + S += "long long"; + return; + case Kunsigned_long_long: + S += "unsigned long long"; + return; + case K__int128: + S += "__int128"; + return; + case Kunsigned__int128: + S += "unsigned __int128"; + return; + case Kfloat: + S += "float"; + return; + case Kdouble: + S += "double"; + return; + case Klong_double: + S += "long double"; + return; + case K__float128: + S += "__float128"; + return; + case Kellipsis: + S += "..."; + return; + case Kdecimal64: + S += "decimal64"; + return; + case Kdecimal128: + S += "decimal128"; + return; + case Kdecimal32: + S += "decimal32"; + return; + case Kdecimal16: + S += "decimal16"; + return; + case Kchar32_t: + S += "char32_t"; + return; + case Kchar16_t: + S += "char16_t"; + return; + case Kauto: + S += "auto"; + return; + case Kdecltype_auto: + S += "decltype(auto)"; + return; + case Knullptr_t: + S += "std::nullptr_t"; + return; + } + } +}; + class ElaboratedTypeSpefType : public Node { - StringView Kind; - Node *Child; public: - ElaboratedTypeSpefType(StringView Kind_, Node *Child_) - : Node(KElaboratedTypeSpefType), Kind(Kind_), Child(Child_) {} + enum Kind { Kstruct, Kunion, Kenum }; + + Kind K; + Node *Child; + + ElaboratedTypeSpefType(Kind K_, Node *Child_) + : Node(KElaboratedTypeSpefType), K(K_), Child(Child_) {} void printLeft(OutputStream &S) const override { - S += Kind; - S += ' '; + static constexpr const char *Elaborate[] = {"struct ", "union ", "enum "}; + S += Elaborate[K]; Child->print(S); } }; @@ -364,9 +590,20 @@ } }; +struct DefaultArg final : Node { + size_t Number; + Node *Name; + + DefaultArg(size_t Number_, Node *Name_) + : Node(KDefaultArg), Number(Number_), Name(Name_) {} + + void printLeft(OutputStream &S) const override { Name->printLeft(S); } +}; + class EnableIfAttr : public Node { - NodeArray Conditions; public: + NodeArray Conditions; + EnableIfAttr(NodeArray Conditions_) : Node(KEnableIfAttr), Conditions(Conditions_) {} @@ -378,12 +615,12 @@ }; class ObjCProtoName : public Node { +public: Node *Ty; StringView Protocol; friend class PointerType; -public: ObjCProtoName(Node *Ty_, StringView Protocol_) : Node(KObjCProtoName), Ty(Ty_), Protocol(Protocol_) {} @@ -401,9 +638,9 @@ }; class PointerType final : public Node { +public: const Node *Pointee; -public: PointerType(Node *Pointee_) : Node(KPointerType, Pointee_->RHSComponentCache), Pointee(Pointee_) {} @@ -447,9 +684,6 @@ // 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 @@ -469,6 +703,9 @@ } public: + const Node *Pointee; + ReferenceKind RK; + ReferenceType(Node *Pointee_, ReferenceKind RK_) : Node(KReferenceType, Pointee_->RHSComponentCache), Pointee(Pointee_), RK(RK_) {} @@ -502,10 +739,10 @@ }; class PointerToMemberType final : public Node { +public: const Node *ClassType; const Node *MemberType; -public: PointerToMemberType(Node *ClassType_, Node *MemberType_) : Node(KPointerToMemberType, MemberType_->RHSComponentCache), ClassType(ClassType_), MemberType(MemberType_) {} @@ -568,10 +805,10 @@ }; class ArrayType final : public Node { +public: Node *Base; NodeOrString Dimension; -public: ArrayType(Node *Base_, NodeOrString Dimension_) : Node(KArrayType, /*RHSComponentCache=*/Cache::Yes, @@ -604,13 +841,13 @@ }; class FunctionType final : public Node { +public: Node *Ret; NodeArray Params; Qualifiers CVQuals; FunctionRefQual RefQual; Node *ExceptionSpec; -public: FunctionType(Node *Ret_, NodeArray Params_, Qualifiers CVQuals_, FunctionRefQual RefQual_, Node *ExceptionSpec_) : Node(KFunctionType, @@ -660,20 +897,25 @@ }; class NoexceptSpec : public Node { - Node *E; public: + Node *E; + NoexceptSpec(Node *E_) : Node(KNoexceptSpec), E(E_) {} void printLeft(OutputStream &S) const override { - S += "noexcept("; - E->print(S); - S += ")"; + S += "noexcept"; + if (E) { + S += "("; + E->print(S); + S += ")"; + } } }; class DynamicExceptionSpec : public Node { - NodeArray Types; public: + NodeArray Types; + DynamicExceptionSpec(NodeArray Types_) : Node(KDynamicExceptionSpec), Types(Types_) {} @@ -685,6 +927,7 @@ }; class FunctionEncoding final : public Node { +public: Node *Ret; Node *Name; NodeArray Params; @@ -692,7 +935,6 @@ Qualifiers CVQuals; FunctionRefQual RefQual; -public: FunctionEncoding(Node *Ret_, Node *Name_, NodeArray Params_, Node *Attrs_, Qualifiers CVQuals_, FunctionRefQual RefQual_) : Node(KFunctionEncoding, @@ -745,9 +987,9 @@ }; class LiteralOperator : public Node { +public: const Node *OpName; -public: LiteralOperator(Node *OpName_) : Node(KLiteralOperator), OpName(OpName_) {} void printLeft(OutputStream &S) const override { @@ -770,6 +1012,38 @@ } }; +class SpecialNameX final : public Node { +public: + enum Kind { + KVTable, + KVTT, + KTypeinfo, + KTypename, + KThreadWrapper, + KThreadInit, + KGuardVar, + }; + const Kind K; + const Node *Child; + + SpecialNameX(Kind K_, Node* Child_) + : Node(KSpecialNameX), K(K_), Child(Child_) {} + + void printLeft(OutputStream &S) const override { + static constexpr const char *Special[] = { + "vtable for ", + "VTT for ", + "typeinfo for ", + "typeinfo name for ", + "thread-local wrapper routine for ", + "thread-local initialization routine for ", + "guard variable for ", + }; + S += Special[K]; + Child->print(S); + } +}; + class CtorVtableSpecialName final : public Node { const Node *FirstType; const Node *SecondType; @@ -803,6 +1077,17 @@ } }; +class FullNestedName final : public Node { +public: + Node *Name; + + FullNestedName(Node *Name_) : Node(KFullNestedName), Name(Name_) {} + + StringView getBaseName() const override { return Name->getBaseName(); } + + void printLeft(OutputStream &S) const override { Name->printLeft(S); } +}; + struct LocalName : Node { Node *Encoding; Node *Entity; @@ -999,9 +1284,9 @@ }; class TemplateArgs final : public Node { +public: NodeArray Params; -public: TemplateArgs(NodeArray Params_) : Node(KTemplateArgs), Params(Params_) {} NodeArray getParams() { return Params; } @@ -1030,6 +1315,11 @@ Cache::Unknown), Index(Index_) {} + ForwardTemplateReference(size_t Index_, Node *Ref_) + : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown, + Cache::Unknown), + Index(Index_), Ref(Ref_) {} + bool hasRHSComponentSlow(OutputStream &S) const override { if (Printing) return false; @@ -1075,7 +1365,8 @@ Node *TemplateArgs; NameWithTemplateArgs(Node *Name_, Node *TemplateArgs_) - : Node(KNameWithTemplateArgs), Name(Name_), TemplateArgs(TemplateArgs_) {} + : Node(KNameWithTemplateArgs), Name(Name_), + TemplateArgs(TemplateArgs_) {} StringView getBaseName() const override { return Name->getBaseName(); } @@ -1102,8 +1393,10 @@ struct StdQualifiedName : Node { Node *Child; + bool Local; - StdQualifiedName(Node *Child_) : Node(KStdQualifiedName), Child(Child_) {} + StdQualifiedName(Node *Child_, bool Local_) + : Node(KStdQualifiedName), Child(Child_), Local(Local_) {} StringView getBaseName() const override { return Child->getBaseName(); } @@ -1113,6 +1406,33 @@ } }; +struct StdName: Node { + StdName() : Node(KStdName) {} + void printLeft(OutputStream &S) const override { S += "std"; } +}; + +struct Substitution: Node { + size_t Index; + Node *Ref; + + Substitution(size_t Index_, Node *Ref_) + : Node(KSubstitution), Index(Index_), Ref(Ref_) {} + + bool hasRHSComponentSlow(OutputStream &S) const override { + return Ref->hasRHSComponent(S); + } + bool hasArraySlow(OutputStream &S) const override { return Ref->hasArray(S); } + bool hasFunctionSlow(OutputStream &S) const override { + return Ref->hasFunction(S); + } + const Node *getSyntaxNode(OutputStream &S) const override { + return Ref->getSyntaxNode(S); + } + + void printLeft(OutputStream &S) const override { Ref->printLeft(S); } + void printRight(OutputStream &S) const override { Ref->printRight(S); } +}; + enum class SpecialSubKind { allocator, basic_string, @@ -1222,11 +1542,14 @@ class CtorDtorName final : public Node { const Node *Basename; - const bool IsDtor; public: - CtorDtorName(Node *Basename_, bool IsDtor_) - : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_) {} + const bool IsDtor; + const uint8_t Flavor; + + CtorDtorName(Node *Basename_, bool IsDtor_, uint8_t Flavor_) + : Node(KCtorDtorName), Basename(Basename_), IsDtor(IsDtor_), + Flavor(Flavor_) {} void printLeft(OutputStream &S) const override { if (IsDtor) @@ -1261,10 +1584,10 @@ }; class ClosureTypeName : public Node { +public: NodeArray Params; StringView Count; -public: ClosureTypeName(NodeArray Params_, StringView Count_) : Node(KClosureTypeName), Params(Params_), Count(Count_) {} @@ -1290,6 +1613,26 @@ } }; +class TemplateExpression : public Node { +public: + Node *Expr; + + TemplateExpression(Node *Expr_) : Node(KTemplateExpression), Expr(Expr_) {} + + bool hasRHSComponentSlow(OutputStream &S) const override { + return Expr->hasRHSComponent(S); + } + bool hasArraySlow(OutputStream &S) const override { + return Expr->hasArray(S); + } + bool hasFunctionSlow(OutputStream &S) const override { + return Expr->hasFunction(S); + } + + void printLeft(OutputStream &S) const override { Expr->printLeft(S); } + void printRight(OutputStream &S) const override { Expr->printRight(S); } +}; + // -- Expression Nodes -- struct Expr : public Node { @@ -1297,32 +1640,76 @@ }; class BinaryExpr : public Expr { +public: + enum Operator { + Oamp_amp, + Oamp, + Oamp_eq, + Oeq, + Ocomma, + Oslash, + Oslash_eq, + Ocaret, + Ocaret_eq, + Oeq_eq, + Ogt_eq, + Ogt, + Olt_eq, + Olt_lt, + Olt_lt_eq, + Olt, + Osub, + Osub_eq, + Omul, + Omul_eq, + Onot_eq, + Oor_or, + Oor, + Oor_eq, + Oarrow_mul, + Oplus, + Oplus_eq, + Omod, + Omod_eq, + Ogt_gt, + Ogt_gt_eq, + }; + +private: + static constexpr const char *const OpStr[] = { + "&&", "&", "&=", "=", ",", "/", "/=", "^", "^=", "==", ">=", + ">", "<=", "<<", "<<=", "<", "-", "-=", "*", "*=", "!=", "||", + "|", "|=", "->*", "+", "+=", "%", "%=", ">>", ">>=", + }; + +public: const Node *LHS; - const StringView InfixOperator; + const Operator InfixOperator; const Node *RHS; -public: - BinaryExpr(Node *LHS_, StringView InfixOperator_, Node *RHS_) - : LHS(LHS_), InfixOperator(InfixOperator_), RHS(RHS_) {} + BinaryExpr(Node *LHS_, Operator InfixOperator_, Node *RHS_) + : Expr(KBinaryExpr), 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 == ">") + if (InfixOperator == Ogt) S += "("; S += "("; LHS->print(S); S += ") "; - S += InfixOperator; + S += OpStr[InfixOperator]; S += " ("; RHS->print(S); S += ")"; - if (InfixOperator == ">") + if (InfixOperator == Ogt) S += ")"; } }; +const char *const BinaryExpr::OpStr[]; class ArraySubscriptExpr : public Expr { const Node *Op1; @@ -1408,6 +1795,42 @@ } }; +class EnclosingExprX : public Expr { +public: + enum Kind { + Ksizeof, + KdecltypeId, + Kdecltype, + }; + + const Kind K; + const Node *Infix; + +private: + static constexpr const char *Prefix[] = { + "sizeof (", + "decltype (", + "decltype (", + }; + static constexpr const char *Postfix[] = { + ")", + ")", + ")", + }; + +public: + EnclosingExprX(Kind K_, Node *Infix_) + : Expr(KEnclosingExprX), K(K_), Infix(Infix_) {} + + void printLeft(OutputStream &S) const override { + S += Prefix[K]; + Infix->print(S); + S += Postfix[K]; + } +}; +const char *const EnclosingExprX::Prefix[]; +const char *const EnclosingExprX::Postfix[]; + class CastExpr : public Expr { // cast_kind(from) const StringView CastKind; @@ -1428,11 +1851,24 @@ } }; +class SizeofAliasParamPackExpr : public Expr { +public: + NodeArray Pack; + + SizeofAliasParamPackExpr(NodeArray Pack_) : Expr(KSizeofAliasParamPackExpr), Pack(Pack_) {} + + void printLeft(OutputStream &S) const override { + S += "sizeof... ("; + Pack.printWithComma(S); + S += ")"; + } +}; + class SizeofParamPackExpr : public Expr { +public: Node *Pack; -public: - SizeofParamPackExpr(Node *Pack_) : Pack(Pack_) {} + SizeofParamPackExpr(Node *Pack_) : Expr(KSizeofParamPackExpr), Pack(Pack_) {} void printLeft(OutputStream &S) const override { S += "sizeof...("; @@ -1527,14 +1963,17 @@ }; class FunctionParam : public Expr { - StringView Number; - public: - FunctionParam(StringView Number_) : Number(Number_) {} + Qualifiers CVR; + size_t Level; + size_t Number; + + FunctionParam(Qualifiers CVR_, size_t Level_, size_t Number_) + : Expr(KFunctionParam), CVR(CVR_), Level(Level_), Number(Number_) {} void printLeft(OutputStream &S) const override { S += "fp"; - S += Number; + S << Number; } }; @@ -1703,17 +2142,29 @@ }; class IntegerExpr : public Expr { - StringView Type; +public: + BuiltinType::Kind Type; StringView Value; -public: - IntegerExpr(StringView Type_, StringView Value_) : Type(Type_), Value(Value_) {} + IntegerExpr(BuiltinType::Kind Type_, StringView Value_) + : Expr(KIntegerExpr), Type(Type_), Value(Value_) {} void printLeft(OutputStream &S) const override { - if (Type.size() > 3) { + switch (Type) { + case BuiltinType::Kwchar_t: + case BuiltinType::Kchar: + case BuiltinType::Ksigned_char: + case BuiltinType::Kunsigned_char: + case BuiltinType::Kshort: + case BuiltinType::Kunsigned_short: + case BuiltinType::K__int128: + case BuiltinType::Kunsigned__int128: S += "("; - S += Type; + BuiltinType(Type).printLeft(S); S += ")"; + break; + default: + break; } if (Value[0] == 'n') { @@ -1722,8 +2173,27 @@ } else S += Value; - if (Type.size() <= 3) - S += Type; + switch (Type) { + case BuiltinType::Kint: + break; + case BuiltinType::Kunsigned_int: + S += "u"; + break; + case BuiltinType::Klong: + S += "l"; + break; + case BuiltinType::Kunsigned_long: + S += "ul"; + break; + case BuiltinType::Klong_long: + S += "ll"; + break; + case BuiltinType::Kunsigned_long_long: + S += "ull"; + break; + default: + break; + } } }; @@ -2046,8 +2516,8 @@ /// Parse the production. Node *parseExpr(); Node *parsePrefixExpr(StringView Kind); - Node *parseBinaryExpr(StringView Kind); - Node *parseIntegerLiteral(StringView Lit); + Node *parseBinaryExpr(BinaryExpr::Operator); + Node *parseIntegerLiteral(BuiltinType::Kind); Node *parseExprPrimary(); template Node *parseFloatingLiteral(); Node *parseFunctionParam(); @@ -2183,10 +2653,17 @@ } if (consumeIf('d')) { - parseNumber(true); + size_t Num; + if (parsePositiveInteger(&Num)) + Num = 0; + else + Num += 1; if (!consumeIf('_')) return nullptr; Node *N = parseName(State); + if (N == nullptr) + return nullptr; + N = make(Num, N); if (N == nullptr) return nullptr; return make(Encoding, N); @@ -2203,11 +2680,12 @@ // ::= St # ::std:: // extension ::= StL Node *Db::parseUnscopedName(NameState *State) { - if (consumeIf("StL") || consumeIf("St")) { + if (consumeIf("St")) { + bool Local = consumeIf('L'); Node *R = parseUnqualifiedName(State); if (R == nullptr) return nullptr; - return make(R); + return make(R, Local); } return parseUnqualifiedName(State); } @@ -2345,30 +2823,32 @@ switch (look(1)) { case 'a': First += 2; - return make("operator&&"); + return make(OperatorName::Oamp_amp); case 'd': + First += 2; + return make(OperatorName::Oamp1); case 'n': First += 2; - return make("operator&"); + return make(OperatorName::Oamp); case 'N': First += 2; - return make("operator&="); + return make(OperatorName::Oamp_eq); case 'S': First += 2; - return make("operator="); + return make(OperatorName::Oeq); } return nullptr; case 'c': switch (look(1)) { case 'l': First += 2; - return make("operator()"); + return make(OperatorName::Ocall); case 'm': First += 2; - return make("operator,"); + return make(OperatorName::Ocomma); case 'o': First += 2; - return make("operator~"); + return make(OperatorName::Otilde); // ::= cv # (cast) case 'v': { First += 2; @@ -2391,55 +2871,55 @@ switch (look(1)) { case 'a': First += 2; - return make("operator delete[]"); + return make(OperatorName::Odel_arr); case 'e': First += 2; - return make("operator*"); + return make(OperatorName::Oderef); case 'l': First += 2; - return make("operator delete"); + return make(OperatorName::Odel); case 'v': First += 2; - return make("operator/"); + return make(OperatorName::Oslash); case 'V': First += 2; - return make("operator/="); + return make(OperatorName::Oslash_eq); } return nullptr; case 'e': switch (look(1)) { case 'o': First += 2; - return make("operator^"); + return make(OperatorName::Ocaret); case 'O': First += 2; - return make("operator^="); + return make(OperatorName::Ocaret_eq); case 'q': First += 2; - return make("operator=="); + return make(OperatorName::Oeq_eq); } return nullptr; case 'g': switch (look(1)) { case 'e': First += 2; - return make("operator>="); + return make(OperatorName::Ogt_eq); case 't': First += 2; - return make("operator>"); + return make(OperatorName::Ogt); } return nullptr; case 'i': if (look(1) == 'x') { First += 2; - return make("operator[]"); + return make(OperatorName::Oindex); } return nullptr; case 'l': switch (look(1)) { case 'e': First += 2; - return make("operator<="); + return make(OperatorName::Olt_eq); // ::= li # operator "" case 'i': { First += 2; @@ -2450,114 +2930,114 @@ } case 's': First += 2; - return make("operator<<"); + return make(OperatorName::Olt_lt); case 'S': First += 2; - return make("operator<<="); + return make(OperatorName::Olt_lt_eq); case 't': First += 2; - return make("operator<"); + return make(OperatorName::Olt); } return nullptr; case 'm': switch (look(1)) { case 'i': First += 2; - return make("operator-"); + return make(OperatorName::Osub); case 'I': First += 2; - return make("operator-="); + return make(OperatorName::Osub_eq); case 'l': First += 2; - return make("operator*"); + return make(OperatorName::Omul); case 'L': First += 2; - return make("operator*="); + return make(OperatorName::Omul_eq); case 'm': First += 2; - return make("operator--"); + return make(OperatorName::Osub_sub); } return nullptr; case 'n': switch (look(1)) { case 'a': First += 2; - return make("operator new[]"); + return make(OperatorName::Onew_arr); case 'e': First += 2; - return make("operator!="); + return make(OperatorName::Onot_eq); case 'g': First += 2; - return make("operator-"); + return make(OperatorName::Oneg); case 't': First += 2; - return make("operator!"); + return make(OperatorName::Onot); case 'w': First += 2; - return make("operator new"); + return make(OperatorName::Onew); } return nullptr; case 'o': switch (look(1)) { case 'o': First += 2; - return make("operator||"); + return make(OperatorName::Oor_or); case 'r': First += 2; - return make("operator|"); + return make(OperatorName::Oor); case 'R': First += 2; - return make("operator|="); + return make(OperatorName::Oor_eq); } return nullptr; case 'p': switch (look(1)) { case 'm': First += 2; - return make("operator->*"); + return make(OperatorName::Oarrow_mul); case 'l': First += 2; - return make("operator+"); + return make(OperatorName::Oplus); case 'L': First += 2; - return make("operator+="); + return make(OperatorName::Oplus_eq); case 'p': First += 2; - return make("operator++"); + return make(OperatorName::Oplus_plus); case 's': First += 2; - return make("operator+"); + return make(OperatorName::Oplus1); case 't': First += 2; - return make("operator->"); + return make(OperatorName::Oarrow); } return nullptr; case 'q': if (look(1) == 'u') { First += 2; - return make("operator?"); + return make(OperatorName::Oternary); } return nullptr; case 'r': switch (look(1)) { case 'm': First += 2; - return make("operator%"); + return make(OperatorName::Omod); case 'M': First += 2; - return make("operator%="); + return make(OperatorName::Omod_eq); case 's': First += 2; - return make("operator>>"); + return make(OperatorName::Ogt_gt); case 'S': First += 2; - return make("operator>>="); + return make(OperatorName::Ogt_gt_eq); } return nullptr; case 's': if (look(1) == 's') { First += 2; - return make("operator<=>"); + return make(OperatorName::Olt_eq_gt); } return nullptr; // ::= v # vendor extended operator @@ -2600,20 +3080,22 @@ bool IsInherited = consumeIf('I'); if (look() != '1' && look() != '2' && look() != '3' && look() != '5') return nullptr; + uint8_t Flavor = look()-'0'; ++First; if (State) State->CtorDtorConversion = true; if (IsInherited) { if (parseName(State) == nullptr) return nullptr; } - return make(SoFar, false); + return make(SoFar, false, Flavor); } if (look() == 'D' && (look(1) == '0' || look(1) == '1' || look(1) == '2' || look(1) == '5')) { + uint8_t Flavor = look(1) - '0'; First += 2; if (State) State->CtorDtorConversion = true; - return make(SoFar, true); + return make(SoFar, true, Flavor); } return nullptr; @@ -2658,7 +3140,7 @@ }; if (consumeIf("St")) - SoFar = make("std"); + SoFar = make(); while (!consumeIf('E')) { consumeIf('L'); // extension @@ -2739,7 +3221,7 @@ return nullptr; Subs.pop_back(); - return SoFar; + return make(SoFar); } // ::= [ ] @@ -2966,7 +3448,7 @@ Node *ExceptionSpec = nullptr; if (consumeIf("Do")) { - ExceptionSpec = make("noexcept"); + ExceptionSpec = make(nullptr); } else if (consumeIf("DO")) { Node *E = parseExpr(); if (E == nullptr || !consumeIf('E')) @@ -3061,14 +3543,19 @@ Node *Db::parseDecltype() { if (!consumeIf('D')) return nullptr; - if (!consumeIf('t') && !consumeIf('T')) + EnclosingExprX::Kind K; + if (consumeIf('t')) + K = EnclosingExprX::KdecltypeId; + else if(consumeIf('T')) + K = EnclosingExprX::Kdecltype; + else return nullptr; Node *E = parseExpr(); if (E == nullptr) return nullptr; if (!consumeIf('E')) return nullptr; - return make("decltype(", E, ")"); + return make(K, E); } // ::= A _ @@ -3123,19 +3610,22 @@ // ::= Tu # dependent elaborated type specifier using 'union' // ::= Te # dependent elaborated type specifier using 'enum' Node *Db::parseClassEnumType() { - StringView ElabSpef; + bool ElaborationFound = true; + ElaboratedTypeSpefType::Kind ElabSpef; if (consumeIf("Ts")) - ElabSpef = "struct"; + ElabSpef = ElaboratedTypeSpefType::Kstruct; else if (consumeIf("Tu")) - ElabSpef = "union"; + ElabSpef = ElaboratedTypeSpefType::Kunion; else if (consumeIf("Te")) - ElabSpef = "enum"; + ElabSpef = ElaboratedTypeSpefType::Kenum; + else + ElaborationFound = false; Node *Name = parseName(); if (Name == nullptr) return nullptr; - if (!ElabSpef.empty()) + if (ElaborationFound) return make(ElabSpef, Name); return Name; @@ -3233,87 +3723,87 @@ // ::= v # void case 'v': ++First; - return make("void"); + return make(BuiltinType::Kvoid); // ::= w # wchar_t case 'w': ++First; - return make("wchar_t"); + return make(BuiltinType::Kwchar_t); // ::= b # bool case 'b': ++First; - return make("bool"); + return make(BuiltinType::Kbool); // ::= c # char case 'c': ++First; - return make("char"); + return make(BuiltinType::Kchar); // ::= a # signed char case 'a': ++First; - return make("signed char"); + return make(BuiltinType::Ksigned_char); // ::= h # unsigned char case 'h': ++First; - return make("unsigned char"); + return make(BuiltinType::Kunsigned_char); // ::= s # short case 's': ++First; - return make("short"); + return make(BuiltinType::Kshort); // ::= t # unsigned short case 't': ++First; - return make("unsigned short"); + return make(BuiltinType::Kunsigned_short); // ::= i # int case 'i': ++First; - return make("int"); + return make(BuiltinType::Kint); // ::= j # unsigned int case 'j': ++First; - return make("unsigned int"); + return make(BuiltinType::Kunsigned_int); // ::= l # long case 'l': ++First; - return make("long"); + return make(BuiltinType::Klong); // ::= m # unsigned long case 'm': ++First; - return make("unsigned long"); + return make(BuiltinType::Kunsigned_long); // ::= x # long long, __int64 case 'x': ++First; - return make("long long"); + return make(BuiltinType::Klong_long); // ::= y # unsigned long long, __int64 case 'y': ++First; - return make("unsigned long long"); + return make(BuiltinType::Kunsigned_long_long); // ::= n # __int128 case 'n': ++First; - return make("__int128"); + return make(BuiltinType::K__int128); // ::= o # unsigned __int128 case 'o': ++First; - return make("unsigned __int128"); + return make(BuiltinType::Kunsigned__int128); // ::= f # float case 'f': ++First; - return make("float"); + return make(BuiltinType::Kfloat); // ::= d # double case 'd': ++First; - return make("double"); + return make(BuiltinType::Kdouble); // ::= e # long double, __float80 case 'e': ++First; - return make("long double"); + return make(BuiltinType::Klong_double); // ::= g # __float128 case 'g': ++First; - return make("__float128"); + return make(BuiltinType::K__float128); // ::= z # ellipsis case 'z': ++First; - return make("..."); + return make(BuiltinType::Kellipsis); // ::= u # vendor extended type case 'u': { @@ -3470,7 +3960,7 @@ Node *P = parseType(); if (P == nullptr) return nullptr; - Result = make(P, " complex"); + Result = make(P, PostfixQualifiedType::KComplex); break; } // ::= G # imaginary (C99) @@ -3479,7 +3969,7 @@ Node *P = parseType(); if (P == nullptr) return P; - Result = make(P, " imaginary"); + Result = make(P, PostfixQualifiedType::KImaginary); break; } // ::= # See Compression below @@ -3535,20 +4025,20 @@ return make(Kind, E); } -Node *Db::parseBinaryExpr(StringView Kind) { +Node *Db::parseBinaryExpr(BinaryExpr::Operator Op) { Node *LHS = parseExpr(); if (LHS == nullptr) return nullptr; Node *RHS = parseExpr(); if (RHS == nullptr) return nullptr; - return make(LHS, Kind, RHS); + return make(LHS, Op, RHS); } -Node *Db::parseIntegerLiteral(StringView Lit) { +Node *Db::parseIntegerLiteral(BuiltinType::Kind K) { StringView Tmp = parseNumber(true); if (!Tmp.empty() && consumeIf('E')) - return make(Lit, Tmp); + return make(K, Tmp); return nullptr; } @@ -3569,25 +4059,26 @@ // ::= fL p _ # L > 0, first parameter // ::= fL p _ # L > 0, second and later parameters Node *Db::parseFunctionParam() { - if (consumeIf("fp")) { - parseCVQualifiers(); - StringView Num = parseNumber(); - if (!consumeIf('_')) + if (!consumeIf('f')) + return nullptr; + size_t Level = 0; + if (consumeIf("L")) { + if (parsePositiveInteger(&Level)) return nullptr; - return make(Num); + ++Level; } - if (consumeIf("fL")) { - if (parseNumber().empty()) - return nullptr; - if (!consumeIf('p')) + if (!consumeIf('p')) + return nullptr; + Qualifiers CVR = parseCVQualifiers(); + size_t Num = 0; + if (!consumeIf('_')) { + if (parsePositiveInteger(&Num)) return nullptr; - parseCVQualifiers(); - StringView Num = parseNumber(); + ++Num; if (!consumeIf('_')) return nullptr; - return make(Num); } - return nullptr; + return make(CVR, Level, Num); } // [gs] nw * _ E # new (expr-list) type @@ -3670,7 +4161,7 @@ switch (look()) { case 'w': ++First; - return parseIntegerLiteral("wchar_t"); + return parseIntegerLiteral(BuiltinType::Kwchar_t); case 'b': if (consumeIf("b0E")) return make(0); @@ -3679,43 +4170,43 @@ return nullptr; case 'c': ++First; - return parseIntegerLiteral("char"); + return parseIntegerLiteral(BuiltinType::Kchar); case 'a': ++First; - return parseIntegerLiteral("signed char"); + return parseIntegerLiteral(BuiltinType::Ksigned_char); case 'h': ++First; - return parseIntegerLiteral("unsigned char"); + return parseIntegerLiteral(BuiltinType::Kunsigned_char); case 's': ++First; - return parseIntegerLiteral("short"); + return parseIntegerLiteral(BuiltinType::Kshort); case 't': ++First; - return parseIntegerLiteral("unsigned short"); + return parseIntegerLiteral(BuiltinType::Kunsigned_short); case 'i': ++First; - return parseIntegerLiteral(""); + return parseIntegerLiteral(BuiltinType::Kint); case 'j': ++First; - return parseIntegerLiteral("u"); + return parseIntegerLiteral(BuiltinType::Kunsigned_int); case 'l': ++First; - return parseIntegerLiteral("l"); + return parseIntegerLiteral(BuiltinType::Klong); case 'm': ++First; - return parseIntegerLiteral("ul"); + return parseIntegerLiteral(BuiltinType::Kunsigned_long); case 'x': ++First; - return parseIntegerLiteral("ll"); + return parseIntegerLiteral(BuiltinType::Klong_long); case 'y': ++First; - return parseIntegerLiteral("ull"); + return parseIntegerLiteral(BuiltinType::Kunsigned_long_long); case 'n': ++First; - return parseIntegerLiteral("__int128"); + return parseIntegerLiteral(BuiltinType::K__int128); case 'o': ++First; - return parseIntegerLiteral("unsigned __int128"); + return parseIntegerLiteral(BuiltinType::Kunsigned__int128); case 'f': ++First; return parseFloatingLiteral(); @@ -3933,19 +4424,19 @@ switch (First[1]) { case 'a': First += 2; - return parseBinaryExpr("&&"); + return parseBinaryExpr(BinaryExpr::Oamp_amp); case 'd': First += 2; return parsePrefixExpr("&"); case 'n': First += 2; - return parseBinaryExpr("&"); + return parseBinaryExpr(BinaryExpr::Oamp); case 'N': First += 2; - return parseBinaryExpr("&="); + return parseBinaryExpr(BinaryExpr::Oamp_eq); case 'S': First += 2; - return parseBinaryExpr("="); + return parseBinaryExpr(BinaryExpr::Oeq); case 't': { First += 2; Node *Ty = parseType(); @@ -3992,7 +4483,7 @@ } case 'm': First += 2; - return parseBinaryExpr(","); + return parseBinaryExpr(BinaryExpr::Ocomma); case 'o': First += 2; return parsePrefixExpr("~"); @@ -4053,33 +4544,33 @@ } case 'v': First += 2; - return parseBinaryExpr("/"); + return parseBinaryExpr(BinaryExpr::Oslash); case 'V': First += 2; - return parseBinaryExpr("/="); + return parseBinaryExpr(BinaryExpr::Oslash_eq); } return nullptr; case 'e': switch (First[1]) { case 'o': First += 2; - return parseBinaryExpr("^"); + return parseBinaryExpr(BinaryExpr::Ocaret); case 'O': First += 2; - return parseBinaryExpr("^="); + return parseBinaryExpr(BinaryExpr::Ocaret_eq); case 'q': First += 2; - return parseBinaryExpr("=="); + return parseBinaryExpr(BinaryExpr::Oeq_eq); } return nullptr; case 'g': switch (First[1]) { case 'e': First += 2; - return parseBinaryExpr(">="); + return parseBinaryExpr(BinaryExpr::Ogt_eq); case 't': First += 2; - return parseBinaryExpr(">"); + return parseBinaryExpr(BinaryExpr::Ogt); } return nullptr; case 'i': @@ -4111,32 +4602,32 @@ switch (First[1]) { case 'e': First += 2; - return parseBinaryExpr("<="); + return parseBinaryExpr(BinaryExpr::Olt_eq); case 's': First += 2; - return parseBinaryExpr("<<"); + return parseBinaryExpr(BinaryExpr::Olt_lt); case 'S': First += 2; - return parseBinaryExpr("<<="); + return parseBinaryExpr(BinaryExpr::Olt_lt_eq); case 't': First += 2; - return parseBinaryExpr("<"); + return parseBinaryExpr(BinaryExpr::Olt); } return nullptr; case 'm': switch (First[1]) { case 'i': First += 2; - return parseBinaryExpr("-"); + return parseBinaryExpr(BinaryExpr::Osub); case 'I': First += 2; - return parseBinaryExpr("-="); + return parseBinaryExpr(BinaryExpr::Osub_eq); case 'l': First += 2; - return parseBinaryExpr("*"); + return parseBinaryExpr(BinaryExpr::Omul); case 'L': First += 2; - return parseBinaryExpr("*="); + return parseBinaryExpr(BinaryExpr::Omul_eq); case 'm': First += 2; if (consumeIf('_')) @@ -4154,7 +4645,7 @@ return parseNewExpr(); case 'e': First += 2; - return parseBinaryExpr("!="); + return parseBinaryExpr(BinaryExpr::Onot_eq); case 'g': First += 2; return parsePrefixExpr("-"); @@ -4175,26 +4666,26 @@ return parseUnresolvedName(); case 'o': First += 2; - return parseBinaryExpr("||"); + return parseBinaryExpr(BinaryExpr::Oor_or); case 'r': First += 2; - return parseBinaryExpr("|"); + return parseBinaryExpr(BinaryExpr::Oor); case 'R': First += 2; - return parseBinaryExpr("|="); + return parseBinaryExpr(BinaryExpr::Oor_eq); } return nullptr; case 'p': switch (First[1]) { case 'm': First += 2; - return parseBinaryExpr("->*"); + return parseBinaryExpr(BinaryExpr::Oarrow_mul); case 'l': First += 2; - return parseBinaryExpr("+"); + return parseBinaryExpr(BinaryExpr::Oplus); case 'L': First += 2; - return parseBinaryExpr("+="); + return parseBinaryExpr(BinaryExpr::Oplus_eq); case 'p': { First += 2; if (consumeIf('_')) @@ -4248,16 +4739,16 @@ } case 'm': First += 2; - return parseBinaryExpr("%"); + return parseBinaryExpr(BinaryExpr::Omod); case 'M': First += 2; - return parseBinaryExpr("%="); + return parseBinaryExpr(BinaryExpr::Omod_eq); case 's': First += 2; - return parseBinaryExpr(">>"); + return parseBinaryExpr(BinaryExpr::Ogt_gt); case 'S': First += 2; - return parseBinaryExpr(">>="); + return parseBinaryExpr(BinaryExpr::Ogt_gt_eq); } return nullptr; case 's': @@ -4286,7 +4777,7 @@ Node *Ty = parseType(); if (Ty == nullptr) return Ty; - return make("sizeof (", Ty, ")"); + return make(EnclosingExprX::Ksizeof, Ty); } case 'z': { First += 2; @@ -4318,9 +4809,7 @@ return nullptr; Names.push_back(Arg); } - return make( - "sizeof... (", make(popTrailingNodeArray(ArgsBegin)), - ")"); + return make(popTrailingNodeArray(ArgsBegin)); } } return nullptr; @@ -4427,7 +4916,7 @@ Node *Ty = parseType(); if (Ty == nullptr) return nullptr; - return make("vtable for ", Ty); + return make(SpecialNameX::KVTable, Ty); } // TT # VTT structure (construction vtable index) case 'T': { @@ -4435,7 +4924,7 @@ Node *Ty = parseType(); if (Ty == nullptr) return nullptr; - return make("VTT for ", Ty); + return make(SpecialNameX::KVTT, Ty); } // TI # typeinfo structure case 'I': { @@ -4443,7 +4932,7 @@ Node *Ty = parseType(); if (Ty == nullptr) return nullptr; - return make("typeinfo for ", Ty); + return make(SpecialNameX::KTypeinfo, Ty); } // TS # typeinfo name (null-terminated byte string) case 'S': { @@ -4451,7 +4940,7 @@ Node *Ty = parseType(); if (Ty == nullptr) return nullptr; - return make("typeinfo name for ", Ty); + return make(SpecialNameX::KTypename, Ty); } // Tc case 'c': { @@ -4483,7 +4972,7 @@ Node *Name = parseName(); if (Name == nullptr) return nullptr; - return make("thread-local wrapper routine for ", Name); + return make(SpecialNameX::KThreadWrapper, Name); } // TH # Thread-local initialization case 'H': { @@ -4491,7 +4980,7 @@ Node *Name = parseName(); if (Name == nullptr) return nullptr; - return make("thread-local initialization routine for ", Name); + return make(SpecialNameX::KThreadInit, Name); } // T default: { @@ -4516,7 +5005,7 @@ Node *Name = parseName(); if (Name == nullptr) return nullptr; - return make("guard variable for ", Name); + return make(SpecialNameX::KGuardVar, Name); } // GR # reference temporary for object // GR _ # First temporary @@ -4745,6 +5234,7 @@ ++Index; if (!consumeIf('_') || Index >= Subs.size()) return nullptr; + return make(Index, Subs[Index]); return Subs[Index]; } @@ -4778,7 +5268,7 @@ if (Index >= TemplateParams.size()) return nullptr; - return TemplateParams[Index]; + return make(Index, TemplateParams[Index]); } // ::= # type or template @@ -4793,7 +5283,7 @@ Node *Arg = parseExpr(); if (Arg == nullptr || !consumeIf('E')) return nullptr; - return Arg; + return make(Arg); } case 'J': { ++First; @@ -4952,6 +5442,461 @@ return false; } +class Mangler { + OutputStream &S; + + void mangle(const NodeArray &A, bool EmptyIsVoid) const { + if (A.empty() && EmptyIsVoid) { + S += "v"; + return; + } + for (Node *P : A) + visit(*P); + } + + void mangle(StringView Tag) const { + S << Tag.size(); + S += Tag; + } + + void mangle(Qualifiers CVQuals) const { + if (CVQuals & QualRestrict) + S += "r"; + if (CVQuals & QualVolatile) + S += "V"; + if (CVQuals & QualConst) + S += "K"; + } + + void mangle(BinaryExpr::Operator O) const { + static constexpr const char *const Mangle[] = { + "aa", "an", "aN", "aS", "cm", "dv", "dV", "eo", "eO", "eq", "ge", + "gt", "le", "ls", "lS", "lt", "mi", "mI", "ml", "mL", "ne", "oo", + "or", "oR", "pm", "pl", "pL", "rm", "rM", "rs", "rS", + }; + S += Mangle[O]; + } + + void mangle(EnclosingExprX::Kind K) const { + static constexpr const char *Mangle[] = { + "st", + "Dt", + "DT", + }; + S += Mangle[K]; + } + + void visitDotSuffix(const DotSuffix &N, const Qualifiers *) const { + visit(*N.Prefix); + S += N.Suffix; + } + void visitVendorExtQualType(const VendorExtQualType &N, + const Qualifiers *) const { + S += "U"; + S << N.Ext.size(); + S += N.Ext; + visit(*N.Ty); + } + void visitQualType(const QualType &N, const Qualifiers *) const { + mangle(N.Quals); + visit(*N.Child); + } + void visitConversionOperatorType(const ConversionOperatorType &N, + const Qualifiers *CVQuals) const { + S += "cv"; + visit(*N.Ty); + } + void visitPostfixQualifiedType(const PostfixQualifiedType &N, + const Qualifiers *) const { + static constexpr char Mangle[] = {'C', 'G'}; + S += Mangle[N.K]; + visit(*N.Ty); + } + void visitElaboratedTypeSpefType(const ElaboratedTypeSpefType &N, + const Qualifiers *) const { + static constexpr const char *Mangle[] = {"Ts", "Tu", "Te"}; + S += Mangle[N.K]; + visit(*N.Child); + } + void visitNameType(const NameType &N, const Qualifiers *) const { + mangle(N.Name); + } + void visitOperatorName(const OperatorName &N, const Qualifiers *) const { + static constexpr const char *Mangle[] = { + "aa", "ad", "an", "aN", "aS", "cl", "cm", "co", "da", "de", "dl", "dv", + "dV", "eo", "eO", "eq", "ge", "gt", "ix", "le", "ls", "lS", "lt", "mi", + "mI", "ml", "mL", "mm", "na", "ne", "ng", "nt", "nw", "oo", "or", "oR", + "pm", "pl", "pL", "pp", "ps", "pt", "qu", "rm", "rM", "rs", "rS", "ss", + }; + S += Mangle[N.K]; + } + void visitBuiltinType(const BuiltinType &N, const Qualifiers *CVQuals) const { + static constexpr const char *Mangle[] = { + "v", "w", "b", "c", "a", "h", "s", "t", "i", "j", + "l", "m", "x", "y", "n", "o", "f", "d", "e", "g", + "e", "Dd", "De", "Df", "Dh", "Di", "Ds", "Da", "Dc", "Dn", + }; + S += Mangle[N.K]; + } + void visitAbiTagAttr(const AbiTagAttr &N, const Qualifiers *) const { + visit(*N.Base); + S += "B"; + mangle(N.Tag); + } + void visitDefaultArg(const DefaultArg &N, const Qualifiers *CVQuals) const { + S += "d"; + if (N.Number) + S << N.Number; + S += "_"; + visit(*N.Name, CVQuals); + } + void visitEnableIfAttr(const EnableIfAttr &N, + const Qualifiers *CVQuals) const { + S += "Ua9enable_ifI"; + mangle(N.Conditions, false); + S += "E"; + } + void visitObjCProtoName(const ObjCProtoName &N, + const Qualifiers *) const { + char Buffer[20]; + OutputStream S1(Buffer, sizeof(Buffer)); + S1 << N.Protocol.size(); + + S += "U"; + S << 9 + S1.getCurrentPosition() + N.Protocol.size(); + S += "objcproto"; + S += StringView(S1.getBuffer(), S1.getCurrentPosition()); + S += N.Protocol; + visit(*N.Ty); + } + void visitPointerType(const PointerType &N, const Qualifiers *CVQuals) const { + S += "P"; + visit(*N.Pointee); + } + void visitReferenceType(const ReferenceType &N, + const Qualifiers *CVQuals) const { + switch (N.RK) { + case ReferenceKind::LValue: + S += "R"; + break; + case ReferenceKind::RValue: + S += "O"; + break; + } + visit(*N.Pointee); + } + void visitPointerToMemberType(const PointerToMemberType &N, + const Qualifiers *CVQuals) const { + S += "M"; + visit(*N.ClassType); + visit(*N.MemberType); + } + void visitArrayType(const ArrayType &N, const Qualifiers *CVQuals) const { + S += "A"; + if (N.Dimension.isString()) + S += N.Dimension.asString(); + else if (N.Dimension.isNode()) + visit(*N.Dimension.asNode()); + S += "_"; + visit(*N.Base); + } + void visitFunctionType(const FunctionType &N, + const Qualifiers *CVQuals) const { + mangle(N.CVQuals); + if (N.ExceptionSpec) + visit(*N.ExceptionSpec); + S += "F"; + visit(*N.Ret); + mangle(N.Params, true); + + if (N.RefQual == FrefQualLValue) + S += "R"; + else if (N.RefQual == FrefQualRValue) + S += "O"; + S += "E"; + } + void visitNoexceptSpec(const NoexceptSpec &N, + const Qualifiers *CVQuals) const { + if (!N.E) { + S += "Do"; + return; + } + S += "DO"; + visit(*N.E); + S += "E"; + } + void visitDynamicExceptionSpec(const DynamicExceptionSpec &N, + const Qualifiers *CVQuals) const { + S += "Dw"; + mangle(N.Types, false); + S += "E"; + } + void visitFunctionEncoding(const FunctionEncoding &N, + const Qualifiers *CVQuals) const { + visit(*N.Name, &N.CVQuals); + if (N.Attrs) + visit(*N.Attrs); + if (N.Ret) + visit(*N.Ret); + mangle(N.Params, true); + } + void visitLiteralOperator(const LiteralOperator &N, + const Qualifiers *) const { + S += "li"; + visit(*N.OpName); + } + void visitSpecialName(const SpecialName &N, const Qualifiers *CVQuals) const { + } + void visitSpecialNameX(const SpecialNameX &N, const Qualifiers *) const { + static constexpr const char *Mangle[] = {"TV", "TT", "TI", "TS", + "TW", "TH", "GV"}; + S += Mangle[N.K]; + visit(*N.Child); + } + void visitCtorVtableSpecialName(const CtorVtableSpecialName &N, + const Qualifiers *CVQuals) const {} + void visitQualifiedName(const QualifiedName &N, + const Qualifiers *CVQuals) const {} + void visitNestedName(const NestedName &N, const Qualifiers *CVQuals) const { + visit(*N.Qual); + visit(*N.Name); + } + void visitFullNestedName(const FullNestedName &N, + const Qualifiers *CVQuals) const { + S += "N"; + if (CVQuals) + mangle(*CVQuals); + visit(*N.Name); + S += "E"; + } + void visitLocalName(const LocalName &N, const Qualifiers *CVQuals) const { + S += "Z"; + visit(*N.Encoding); + S += "E"; + visit(*N.Entity, CVQuals); + } + void visitVectorType(const VectorType &N, const Qualifiers *CVQuals) const {} + void visitParameterPack(const ParameterPack &N, + const Qualifiers *CVQuals) const {} + void visitTemplateArgumentPack(const TemplateArgumentPack &N, + const Qualifiers *) const { + S += "J"; + mangle(N.getElements(), false); + S += "E"; + } + void visitParameterPackExpansion(const ParameterPackExpansion &N, + const Qualifiers *) const { + S += "Dp"; + visit(*N.getChild()); + } + void visitTemplateArgs(const TemplateArgs &N, + const Qualifiers *CVQuals) const { + S += "I"; + for (Node *P : N.Params) + visit(*P); + S += "E"; + } + void visitTemplateExpression(const TemplateExpression &N, + const Qualifiers *CVQuals) const { + S += "X"; + visit(*N.Expr); + S += "E"; + } + void visitForwardTemplateReference(const ForwardTemplateReference &N, + const Qualifiers *CVQuals) const { + S += "T"; + if (N.Index) + S << N.Index - 1; + S += "_"; + } + void visitNameWithTemplateArgs(const NameWithTemplateArgs &N, + const Qualifiers *CVQuals) const { + visit(*N.Name); + visit(*N.TemplateArgs); + } + void visitGlobalQualifiedName(const GlobalQualifiedName &N, + const Qualifiers *CVQuals) const {} + void visitStdQualifiedName(const StdQualifiedName &N, + const Qualifiers *CVQuals) const { + S += "St"; + if (N.Local) + S += "L"; + visit(*N.Child); + } + void visitStdName(const StdName &N, const Qualifiers *) const { S += "St"; } + void visitSubstitution(const Substitution &N, const Qualifiers *) const { + S += "S"; + switch (N.Index) { + case 0: + break; + case 1: + S += "0"; + break; + default: + std::array Buffer; + size_t Ind = N.Index - 1; + auto I = Buffer.rbegin(); + for (; Ind != 0; Ind /= 36) { + size_t C = Ind % 36; + *I++ = C < 10 ? '0' + C : 'A' + C - 10; + } + S += StringView(I.base(), Buffer.end()); + break; + } + S += "_"; + } + void visitExpandedSpecialSubstitution(const ExpandedSpecialSubstitution &N, + const Qualifiers *CVQuals) const {} + void visitSpecialSubstitution(const SpecialSubstitution &N, + const Qualifiers *CVQuals) const {} + void visitCtorDtorName(const CtorDtorName &N, + const Qualifiers *CVQuals) const { + S += N.IsDtor ? "D" : "C"; + S << N.Flavor; + } + void visitDtorName(const DtorName &N, const Qualifiers *CVQuals) const {} + void visitUnnamedTypeName(const UnnamedTypeName &N, + const Qualifiers *CVQuals) const {} + void visitClosureTypeName(const ClosureTypeName &N, + const Qualifiers *) const { + S += "Ul"; + mangle(N.Params, true); + S += "E"; + S += N.Count; + S += "_"; + } + void visitStructuredBindingName(const StructuredBindingName &N, + const Qualifiers *CVQuals) const {} + void visitExpr(const Expr &N, const Qualifiers *CVQuals) const {} + void visitBinaryExpr(const BinaryExpr &N, const Qualifiers *CVQuals) const { + mangle(N.InfixOperator); + visit(*N.LHS); + visit(*N.RHS); + } + void visitBracedExpr(const BracedExpr &N, const Qualifiers *CVQuals) const {} + void visitBracedRangeExpr(const BracedRangeExpr &N, + const Qualifiers *CVQuals) const {} + void visitEnclosingExprX(const EnclosingExprX &N, + const Qualifiers *CVQuals) const { + mangle(N.K); + visit(*N.Infix); + switch (N.K) { + case EnclosingExprX::Ksizeof: + break; + case EnclosingExprX::KdecltypeId: + case EnclosingExprX::Kdecltype: + S += 'E'; + break; + } + } + void visitFunctionParam(const FunctionParam &N, + const Qualifiers *CVQuals) const { + S += "f"; + if (N.Level > 0) { + S += "L"; + S << N.Level - 1; + } + S += "p"; + mangle(N.CVR); + if (N.Number > 0) + S << N.Number - 1; + S += "_"; + } + void visitIntegerExpr(const IntegerExpr &N, const Qualifiers *CVQuals) const { + S += "L"; + visit(BuiltinType(N.Type)); + S += N.Value; + S += "E"; + } + void visitSizeofAliasParamPackExpr(const SizeofAliasParamPackExpr &N, + const Qualifiers *) const { + S += "sP"; + mangle(N.Pack, false); + S += "E"; + } + void visitSizeofParamPackExpr(const SizeofParamPackExpr &N, + const Qualifiers *) const { + S += "sZ"; + visit(*N.Pack); + } + + void visit(const Node &N, const Qualifiers *CVQuals = nullptr) const; +public: + + Mangler(OutputStream &S_) : S(S_) {} + + void mangle(const Node &N) const { + S += "_Z"; + visit(N); + } +}; + +void Mangler::visit(const Node &N, const Qualifiers *CVQuals) const { +#define CASE(T) \ + case Node::K##T: \ + visit##T(static_cast(N), CVQuals); \ + break + switch (N.getKind()) { + CASE(DotSuffix); + CASE(VendorExtQualType); + CASE(QualType); + CASE(ConversionOperatorType); + CASE(PostfixQualifiedType); + CASE(ElaboratedTypeSpefType); + CASE(NameType); + CASE(OperatorName); + CASE(BuiltinType); + CASE(AbiTagAttr); + CASE(DefaultArg); + CASE(EnableIfAttr); + CASE(ObjCProtoName); + CASE(PointerType); + CASE(ReferenceType); + CASE(PointerToMemberType); + CASE(ArrayType); + CASE(FunctionType); + CASE(NoexceptSpec); + CASE(DynamicExceptionSpec); + CASE(FunctionEncoding); + CASE(LiteralOperator); + CASE(SpecialName); + CASE(SpecialNameX); + CASE(CtorVtableSpecialName); + CASE(QualifiedName); + CASE(NestedName); + CASE(FullNestedName); + CASE(LocalName); + CASE(VectorType); + CASE(ParameterPack); + CASE(TemplateArgumentPack); + CASE(ParameterPackExpansion); + CASE(TemplateArgs); + CASE(TemplateExpression); + CASE(ForwardTemplateReference); + CASE(NameWithTemplateArgs); + CASE(GlobalQualifiedName); + CASE(StdQualifiedName); + CASE(StdName); + CASE(Substitution); + CASE(ExpandedSpecialSubstitution); + CASE(SpecialSubstitution); + CASE(CtorDtorName); + CASE(DtorName); + CASE(UnnamedTypeName); + CASE(ClosureTypeName); + CASE(StructuredBindingName); + CASE(Expr); + CASE(BinaryExpr); + CASE(BracedExpr); + CASE(BracedRangeExpr); + CASE(EnclosingExprX); + CASE(FunctionParam); + CASE(IntegerExpr); + CASE(SizeofAliasParamPackExpr); + CASE(SizeofParamPackExpr); + } +} + } // unnamed namespace char *llvm::itaniumDemangle(const char *MangledName, char *Buf, @@ -5152,6 +6097,17 @@ return printNode(static_cast(RootNode), Buf, N); } +char *ItaniumPartialDemangler::mangle(char *Buf, size_t *N) const { + OutputStream S; + if (initializeOutputStream(Buf, N, S, 128)) + return nullptr; + Mangler(S).mangle(*static_cast(RootNode)); + S += '\0'; + if (N != nullptr) + *N = S.getCurrentPosition(); + return S.getBuffer(); +} + bool ItaniumPartialDemangler::hasFunctionQualifiers() const { assert(RootNode != nullptr && "must call partialDemangle()"); if (!isFunction()) Index: unittests/Demangle/PartialDemangleTest.cpp =================================================================== --- unittests/Demangle/PartialDemangleTest.cpp +++ unittests/Demangle/PartialDemangleTest.cpp @@ -192,3 +192,86 @@ std::free(Buf); } + +TEST(MangleTest, DM) { + llvm::ItaniumPartialDemangler IPD; + size_t Size = 1; + char *Buf = static_cast(std::malloc(Size)); + auto doit = [&](const char *M) { + IPD.partialDemangle(M); + return Buf = IPD.finishDemangle(Buf, &Size); + }; +#define E(x, y) EXPECT_STREQ(x, doit(y)) + E("f()", "_Z1fv"); + E("A::f() const::f", "_ZZNK1A1fEvE1f"); + E("A::f() const::A::f() const", "_ZZNK1A1fEvENK1A1fEv"); + E("S::f(int)::'lambda'()::operator()() const", "_ZZN1S1fEiEd_NKUlvE_clEv"); +#undef E +} + +TEST(MangleTest, M) { + llvm::ItaniumPartialDemangler IPD; + size_t Size = 1; + char *Buf = static_cast(std::malloc(Size)); + auto doit = [&](const char *M) { + IPD.partialDemangle(M); + return Buf = IPD.mangle(Buf, &Size); + }; +#define E(x) EXPECT_STREQ(x, doit(x)) + E("_Z1fv"); + E("_Z1fii"); + E("_ZN1f1gEv"); + E("_ZN1f1g1hEv"); + E("_ZNK1f1gEv"); + E("_ZNrVK1f1gEv"); + E("_ZN1fIvvE1gEv"); + E("_ZN1fIE1gEv"); + E("_Z1fPiRiOiRRi"); + E("_Z1fPFilE"); + E("_Z1fPFivE"); + E("_ZN1AC1Ev"); + E("_ZN1AcviEv"); + E("_Z1fB2XXv"); + E("_Z1fM1Ai"); + E("_Z1fMN1X1AEi"); + E("_Z1fRA10_i"); + E("_Z1fILi2EEvRAplT_Li1E_i"); + E("_Z1fILi1ELi2ELi3ELi4ELi5ELi6ELi7ELi8ELi9ELi10ELi11ELi12EEvRAplplT_T3_T10__i"); + E("_Z1fM1AVKFicE"); + E("_Z1fRFicE"); + E("_Z1fM1AVKFicOE"); + E("_Z1fM1AVKFicRE"); + E("_Z1fPFicE"); + E("_Z1fPDoFicE"); + E("_Z1fIiEvPDOltstT_Li4EEFvvE"); + E("_Z1fIiEvPDwT_EFvvE"); + E("_Z1fUa9enable_ifIXeqfL0p_Li0EEEi"); + E("_Z1fI1AEvT_PDtfL0pK_E"); + E("_ZNKSt1A1fEv"); + E("_ZSt1fv"); + E("_ZStL1fv"); + E("_Z1fIJiiEEvv"); + E("_Z1fIJEEvv"); + E("_Z2f0IJEEv1XIXsZT_EJDpRT_EE"); + E("_Z2f0IJifdEEv1XIXsZT_EJDpRT_EE"); + E("_Z1fN1q1w1e1r1t1y1u1i1o1p1q1w1e1r1t1y1u1i1o1p1QESJ_"); + E("_Z1fN1q1w1e1r1t1y1u1i1o1p1q1w1e1r1t1y1u1i1o1p1q1w1e1r1t1y1u1i1o1p1q1w1e1r1t1y1u1i1o1p1QES13_"); + E("_Z2f8IiJ2idIiES0_IfEEEvRAsPiDpT0_T_DpNS3_4typeEE_i"); + E("_Z1fv.foo"); + E("_Z1fU3exti"); + E("_Z1fKi"); + E("_Z1fCfGf"); + E("_Z1fI1AEvTsNT_1XE"); + E("_Z1fI1AEvTuNT_1XE"); + E("_Z1fI1AEvTeNT_1XE"); + E("_Z1fPU11objcproto1A11objc_object"); + E("_Zli2_le"); + E("_ZTV1A"); + E("_ZTT1A"); + E("_ZTI1A"); + E("_ZTS1A"); + E("_ZTW1A"); + E("_ZTH1A"); + E("_ZGVZ1fvE1a"); + E("_ZZN1S1fEiEd_NKUlvE_clEv"); +}