diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -221,6 +221,17 @@ /// Visit the most-derived object corresponding to this object. template void visit(Fn F) const; + /// Returns true if the tree rooted at this node is equivalent to + /// the tree rooted at the specified 'Root' node. + /// + /// Equivalence of two nodes N1 and N2 is defined as: + /// 1. N1.getKind() == N2.getKind() + /// 2. N1 == N2 where '==' is defined by the + /// kind of N1 and N2. + /// + /// Behaviour is undefined if 'Root == nullptr'. + bool equals(Node const* Root) const; + // The following function is provided by all derived classes: // // Call F with arguments that, when passed to the constructor of this node, @@ -331,6 +342,23 @@ FirstElement = false; } } + + friend bool operator==(NodeArray const& LHS, NodeArray const& RHS) { + if (LHS.size() != RHS.size()) + return false; + + auto** IT1 = LHS.begin(); + auto** IT2 = RHS.begin(); + for (; IT1 != LHS.end(); ++IT1, ++IT2) + if (!(*IT1)->equals(*IT2)) + return false; + + return true; + } + + friend bool operator!=(NodeArray const& LHS, NodeArray const& RHS) { + return !(LHS == RHS); + } }; struct NodeArrayNode : Node { @@ -340,6 +368,14 @@ template void match(Fn F) const { F(Array); } void printLeft(OutputBuffer &OB) const override { Array.printWithComma(OB); } + + friend bool operator==(NodeArrayNode const& LHS, NodeArrayNode const& RHS) { + return LHS.Array == RHS.Array; + } + + friend bool operator!=(NodeArrayNode const& LHS, NodeArrayNode const& RHS) { + return !(LHS == RHS); + } }; class DotSuffix final : public Node { @@ -358,6 +394,14 @@ OB += Suffix; OB += ")"; } + + friend bool operator==(DotSuffix const& LHS, DotSuffix const& RHS) { + return LHS.Suffix == RHS.Suffix && LHS.Prefix->equals(RHS.Prefix); + } + + friend bool operator!=(DotSuffix const& LHS, DotSuffix const& RHS) { + return !(LHS == RHS); + } }; class VendorExtQualType final : public Node { @@ -382,6 +426,16 @@ if (TA != nullptr) TA->print(OB); } + + friend bool operator==(VendorExtQualType const& LHS, VendorExtQualType const& RHS) { + return LHS.Ext == RHS.Ext + && LHS.Ty->equals(RHS.Ty) + && LHS.TA->equals(RHS.TA); + } + + friend bool operator!=(VendorExtQualType const& LHS, VendorExtQualType const& RHS) { + return !(LHS == RHS); + } }; enum FunctionRefQual : unsigned char { @@ -442,6 +496,11 @@ } void printRight(OutputBuffer &OB) const override { Child->printRight(OB); } + + friend bool operator==(QualType const& LHS, QualType const& RHS) { + return LHS.Quals == RHS.Quals + && LHS.Child->equals(RHS.Child); + } }; class ConversionOperatorType final : public Node { @@ -457,6 +516,11 @@ OB += "operator "; Ty->print(OB); } + + friend bool operator==(ConversionOperatorType const& LHS, + ConversionOperatorType const& RHS) { + return LHS.Ty->equals(RHS.Ty); + } }; class PostfixQualifiedType final : public Node { @@ -473,6 +537,12 @@ Ty->printLeft(OB); OB += Postfix; } + + friend bool operator==(PostfixQualifiedType const& LHS, + PostfixQualifiedType const& RHS) { + return LHS.Postfix == RHS.Postfix + && LHS.Ty->equals(RHS.Ty); + } }; class NameType final : public Node { @@ -487,6 +557,10 @@ StringView getBaseName() const override { return Name; } void printLeft(OutputBuffer &OB) const override { OB += Name; } + + friend bool operator==(NameType const& LHS, NameType const& RHS) { + return LHS.Name == RHS.Name; + } }; class BitIntType final : public Node { @@ -507,6 +581,11 @@ Size->printAsOperand(OB); OB.printClose(); } + + friend bool operator==(BitIntType const& LHS, BitIntType const& RHS) { + return LHS.Signed == RHS.Signed + && LHS.Size->equals(RHS.Size); + } }; class ElaboratedTypeSpefType : public Node { @@ -523,6 +602,12 @@ OB += ' '; Child->print(OB); } + + friend bool operator==(ElaboratedTypeSpefType const& LHS, + ElaboratedTypeSpefType const& RHS) { + return LHS.Kind == RHS.Kind + && LHS.Child->equals(RHS.Child); + } }; struct AbiTagAttr : Node { @@ -542,6 +627,11 @@ OB += Tag; OB += "]"; } + + friend bool operator==(AbiTagAttr const& LHS, AbiTagAttr const& RHS) { + return LHS.Tag == RHS.Tag + && LHS.Base->equals(RHS.Base); + } }; class EnableIfAttr : public Node { @@ -557,6 +647,11 @@ Conditions.printWithComma(OB); OB += ']'; } + + friend bool operator==(EnableIfAttr const& LHS, + EnableIfAttr const& RHS) { + return LHS.Conditions == RHS.Conditions; + } }; class ObjCProtoName : public Node { @@ -582,6 +677,12 @@ OB += Protocol; OB += ">"; } + + friend bool operator==(ObjCProtoName const& LHS, + ObjCProtoName const& RHS) { + return LHS.Protocol == RHS.Protocol + && LHS.Ty->equals(RHS.Ty); + } }; class PointerType final : public Node { @@ -626,6 +727,10 @@ Pointee->printRight(OB); } } + + friend bool operator==(PointerType const& LHS, PointerType const& RHS) { + return LHS.Pointee->equals(RHS.Pointee); + } }; enum class ReferenceKind { @@ -708,6 +813,11 @@ OB += ")"; Collapsed.second->printRight(OB); } + + friend bool operator==(ReferenceType const& LHS, ReferenceType const& RHS) { + return LHS.RK == RHS.RK + && LHS.Pointee->equals(RHS.Pointee); + } }; class PointerToMemberType final : public Node { @@ -740,6 +850,11 @@ OB += ")"; MemberType->printRight(OB); } + + friend bool operator==(PointerToMemberType const& LHS, PointerToMemberType const& RHS) { + return LHS.ClassType->equals(RHS.ClassType) + && LHS.MemberType->equals(RHS.MemberType); + } }; class ArrayType final : public Node { @@ -769,6 +884,11 @@ OB += "]"; Base->printRight(OB); } + + friend bool operator==(ArrayType const& LHS, ArrayType const& RHS) { + return LHS.Base->equals(RHS.Base) + && LHS.Dimension->equals(RHS.Dimension); + } }; class FunctionType final : public Node { @@ -829,6 +949,14 @@ ExceptionSpec->print(OB); } } + + friend bool operator==(FunctionType const& LHS, FunctionType const& RHS) { + return LHS.CVQuals == RHS.CVQuals + && LHS.RefQual == RHS.RefQual + && LHS.Params == RHS.Params + && LHS.Ret->equals(RHS.Ret) + && LHS.ExceptionSpec->equals(RHS.ExceptionSpec); + } }; class NoexceptSpec : public Node { @@ -844,6 +972,10 @@ E->printAsOperand(OB); OB.printClose(); } + + friend bool operator==(NoexceptSpec const& LHS, NoexceptSpec const& RHS) { + return LHS.E->equals(RHS.E); + } }; class DynamicExceptionSpec : public Node { @@ -860,6 +992,11 @@ Types.printWithComma(OB); OB.printClose(); } + + friend bool operator==(DynamicExceptionSpec const& LHS, + DynamicExceptionSpec const& RHS) { + return LHS.Types == RHS.Types; + } }; class FunctionEncoding final : public Node { @@ -926,6 +1063,31 @@ if (Attrs != nullptr) Attrs->print(OB); } + + friend bool operator==(FunctionEncoding const& LHS, + FunctionEncoding const& RHS) { + if (LHS.CVQuals != RHS.CVQuals) + return false; + + if (LHS.RefQual != RHS.RefQual) + return false; + + if (!!LHS.Ret != !!RHS.Ret) + return false; + + if (LHS.Ret) + if (!LHS.Ret->equals(RHS.Ret)) + return false; + + if (!!LHS.Attrs != !!RHS.Attrs) + return false; + + if (LHS.Attrs) + if (!LHS.Attrs->equals(RHS.Attrs)) + return false; + + return LHS.Params == RHS.Params; + } }; class LiteralOperator : public Node { @@ -941,6 +1103,11 @@ OB += "operator\"\" "; OpName->print(OB); } + + friend bool operator==(LiteralOperator const& LHS, + LiteralOperator const& RHS) { + return LHS.OpName->equals(RHS.OpName); + } }; class SpecialName final : public Node { @@ -957,6 +1124,12 @@ OB += Special; Child->print(OB); } + + friend bool operator==(SpecialName const& LHS, + SpecialName const& RHS) { + return LHS.Special == RHS.Special + && LHS.Child->equals(RHS.Child); + } }; class CtorVtableSpecialName final : public Node { @@ -976,6 +1149,12 @@ OB += "-in-"; SecondType->print(OB); } + + friend bool operator==(CtorVtableSpecialName const& LHS, + CtorVtableSpecialName const& RHS) { + return LHS.FirstType->equals(RHS.FirstType) + && LHS.SecondType->equals(RHS.SecondType); + } }; struct NestedName : Node { @@ -994,6 +1173,12 @@ OB += "::"; Name->print(OB); } + + friend bool operator==(NestedName const& LHS, + NestedName const& RHS) { + return LHS.Qual->equals(RHS.Qual) + && LHS.Name->equals(RHS.Name); + } }; struct ModuleName : Node { @@ -1016,6 +1201,21 @@ OB += IsPartition ? ':' : '.'; Name->print(OB); } + + friend bool operator==(ModuleName const& LHS, + ModuleName const& RHS) { + if (LHS.IsPartition != RHS.IsPartition) + return false; + + if (!!LHS.Parent != !!RHS.Parent) + return false; + + if (LHS.Parent) + if (!LHS.Parent->equals(RHS.Parent)) + return false; + + return LHS.Name->equals(RHS.Name); + } }; struct ModuleEntity : Node { @@ -1034,6 +1234,12 @@ OB += '@'; Module->print(OB); } + + friend bool operator==(ModuleEntity const& LHS, + ModuleEntity const& RHS) { + return LHS.Module->equals(RHS.Module) + && LHS.Name->equals(RHS.Name); + } }; struct LocalName : Node { @@ -1050,6 +1256,11 @@ OB += "::"; Entity->print(OB); } + + friend bool operator==(LocalName const& LHS, LocalName const& RHS) { + return LHS.Encoding->equals(RHS.Encoding) + && LHS.Entity->equals(RHS.Entity); + } }; class QualifiedName final : public Node { @@ -1070,6 +1281,12 @@ OB += "::"; Name->print(OB); } + + friend bool operator==(QualifiedName const& LHS, + QualifiedName const& RHS) { + return LHS.Qualifier->equals(RHS.Qualifier) + && LHS.Name->equals(RHS.Name); + } }; class VectorType final : public Node { @@ -1092,6 +1309,12 @@ Dimension->print(OB); OB += "]"; } + + friend bool operator==(VectorType const& LHS, + VectorType const& RHS) { + return LHS.BaseType->equals(RHS.BaseType) + && LHS.Dimension->equals(RHS.Dimension); + } }; class PixelVectorType final : public Node { @@ -1109,6 +1332,11 @@ Dimension->print(OB); OB += "]"; } + + friend bool operator==(PixelVectorType const& LHS, + PixelVectorType const& RHS) { + return LHS.Dimension->equals(RHS.Dimension); + } }; class BinaryFPType final : public Node { @@ -1124,6 +1352,11 @@ OB += "_Float"; Dimension->print(OB); } + + friend bool operator==(BinaryFPType const& LHS, + BinaryFPType const& RHS) { + return LHS.Dimension->equals(RHS.Dimension); + } }; enum class TemplateParamKind { Type, NonType, Template }; @@ -1159,6 +1392,12 @@ if (Index > 0) OB << Index - 1; } + + friend bool operator==(SyntheticTemplateParamName const& LHS, + SyntheticTemplateParamName const& RHS) { + return LHS.Kind == RHS.Kind + && LHS.Index == RHS.Index; + } }; /// A template type parameter declaration, 'typename T'. @@ -1174,6 +1413,11 @@ void printLeft(OutputBuffer &OB) const override { OB += "typename "; } void printRight(OutputBuffer &OB) const override { Name->print(OB); } + + friend bool operator==(TypeTemplateParamDecl const& LHS, + TypeTemplateParamDecl const& RHS) { + return LHS.Name->equals(RHS.Name); + } }; /// A non-type template parameter declaration, 'int N'. @@ -1197,6 +1441,12 @@ Name->print(OB); Type->printRight(OB); } + + friend bool operator==(NonTypeTemplateParamDecl const& LHS, + NonTypeTemplateParamDecl const& RHS) { + return LHS.Name->equals(RHS.Name) + && LHS.Type->equals(RHS.Type); + } }; /// A template template parameter declaration, @@ -1220,6 +1470,12 @@ } void printRight(OutputBuffer &OB) const override { Name->print(OB); } + + friend bool operator==(TemplateTemplateParamDecl const& LHS, + TemplateTemplateParamDecl const& RHS) { + return LHS.Name->equals(RHS.Name) + && LHS.Params == RHS.Params; + } }; /// A template parameter pack declaration, 'typename ...T'. @@ -1238,6 +1494,11 @@ } void printRight(OutputBuffer &OB) const override { Param->printRight(OB); } + + friend bool operator==(TemplateParamPackDecl const& LHS, + TemplateParamPackDecl const& RHS) { + return LHS.Param->equals(RHS.Param); + } }; /// An unexpanded parameter pack (either in the expression or type context). If @@ -1312,6 +1573,11 @@ if (Idx < Data.size()) Data[Idx]->printRight(OB); } + + friend bool operator==(ParameterPack const& LHS, + ParameterPack const& RHS) { + return LHS.Data == RHS.Data; + } }; /// A variadic template argument. This node represents an occurrence of @@ -1332,6 +1598,11 @@ void printLeft(OutputBuffer &OB) const override { Elements.printWithComma(OB); } + + friend bool operator==(TemplateArgumentPack const& LHS, + TemplateArgumentPack const& RHS) { + return LHS.Elements == RHS.Elements; + } }; /// A pack expansion. Below this node, there are some unexpanded ParameterPacks @@ -1378,6 +1649,11 @@ Child->print(OB); } } + + friend bool operator==(ParameterPackExpansion const& LHS, + ParameterPackExpansion const& RHS) { + return LHS.Child->equals(RHS.Child); + } }; class TemplateArgs final : public Node { @@ -1396,6 +1672,11 @@ Params.printWithComma(OB); OB += ">"; } + + friend bool operator==(TemplateArgs const& LHS, + TemplateArgs const& RHS) { + return LHS.Params == RHS.Params; + } }; /// A forward-reference to a template argument that was not known at the point @@ -1426,6 +1707,22 @@ // out if more than one print* function is active. mutable bool Printing = false; + friend bool operator==(ForwardTemplateReference const& LHS, + ForwardTemplateReference const& RHS) { + if (LHS.Index != RHS.Index) + return false; + + if (!!LHS.Ref != !!RHS.Ref) + return false; + + if (LHS.Ref) + if (!LHS.Ref->equals(RHS.Ref)) + return false; + + // Ignore 'Printing' member + return true; + } + ForwardTemplateReference(size_t Index_) : Node(KForwardTemplateReference, Cache::Unknown, Cache::Unknown, Cache::Unknown), @@ -1491,6 +1788,12 @@ Name->print(OB); TemplateArgs->print(OB); } + + friend bool operator==(NameWithTemplateArgs const& LHS, + NameWithTemplateArgs const& RHS) { + return LHS.Name->equals(RHS.Name) + && LHS.TemplateArgs->equals(RHS.TemplateArgs); + } }; class GlobalQualifiedName final : public Node { @@ -1508,6 +1811,11 @@ OB += "::"; Child->print(OB); } + + friend bool operator==(GlobalQualifiedName const& LHS, + GlobalQualifiedName const& RHS) { + return LHS.Child->equals(RHS.Child); + } }; enum class SpecialSubKind { @@ -1566,6 +1874,11 @@ OB << ">"; } } + + friend bool operator==(ExpandedSpecialSubstitution const& LHS, + ExpandedSpecialSubstitution const& RHS) { + return LHS.SSK == RHS.SSK; + } }; class SpecialSubstitution final : public ExpandedSpecialSubstitution { @@ -1611,6 +1924,13 @@ OB += "~"; OB += Basename->getBaseName(); } + + friend bool operator==(CtorDtorName const& LHS, + CtorDtorName const& RHS) { + return LHS.IsDtor == RHS.IsDtor + && LHS.Variant == RHS.Variant + && LHS.Basename->equals(RHS.Basename); + } }; class DtorName : public Node { @@ -1625,6 +1945,11 @@ OB += "~"; Base->printLeft(OB); } + + friend bool operator==(DtorName const& LHS, + DtorName const& RHS) { + return LHS.Base->equals(RHS.Base); + } }; class UnnamedTypeName : public Node { @@ -1640,6 +1965,11 @@ OB += Count; OB += "\'"; } + + friend bool operator==(UnnamedTypeName const& LHS, + UnnamedTypeName const& RHS) { + return LHS.Count == RHS.Count; + } }; class ClosureTypeName : public Node { @@ -1675,6 +2005,13 @@ OB += "\'"; printDeclarator(OB); } + + friend bool operator==(ClosureTypeName const& LHS, + ClosureTypeName const& RHS) { + return LHS.TemplateParams == RHS.TemplateParams + && LHS.Params == RHS.Params + && LHS.Count == RHS.Count; + } }; class StructuredBindingName : public Node { @@ -1690,6 +2027,11 @@ Bindings.printWithComma(OB); OB.printClose(']'); } + + friend bool operator==(StructuredBindingName const& LHS, + StructuredBindingName const& RHS) { + return LHS.Bindings == RHS.Bindings; + } }; // -- Expression Nodes -- @@ -1726,6 +2068,13 @@ if (ParenAll) OB.printClose(); } + + friend bool operator==(BinaryExpr const& LHS, + BinaryExpr const& RHS) { + return LHS.InfixOperator == RHS.InfixOperator + && LHS.LHS->equals(RHS.LHS) + && LHS.RHS->equals(RHS.RHS); + } }; class ArraySubscriptExpr : public Node { @@ -1746,6 +2095,12 @@ Op2->printAsOperand(OB); OB.printClose(']'); } + + friend bool operator==(ArraySubscriptExpr const& LHS, + ArraySubscriptExpr const& RHS) { + return LHS.Op1->equals(RHS.Op1) + && LHS.Op2->equals(RHS.Op2); + } }; class PostfixExpr : public Node { @@ -1764,6 +2119,12 @@ Child->printAsOperand(OB, getPrecedence(), true); OB += Operator; } + + friend bool operator==(PostfixExpr const& LHS, + PostfixExpr const& RHS) { + return LHS.Operator == RHS.Operator + && LHS.Child->equals(RHS.Child); + } }; class ConditionalExpr : public Node { @@ -1787,6 +2148,13 @@ OB += " : "; Else->printAsOperand(OB, Prec::Assign, true); } + + friend bool operator==(ConditionalExpr const& LHS, + ConditionalExpr const& RHS) { + return LHS.Cond->equals(RHS.Cond) + && LHS.Then->equals(RHS.Then) + && LHS.Else->equals(RHS.Else); + } }; class MemberExpr : public Node { @@ -1807,6 +2175,13 @@ OB += Kind; RHS->printAsOperand(OB, getPrecedence(), false); } + + friend bool operator==(MemberExpr const& LHS, + MemberExpr const& RHS) { + return LHS.Kind == RHS.Kind + && LHS.LHS->equals(RHS.LHS) + && LHS.RHS->equals(RHS.RHS); + } }; class SubobjectExpr : public Node { @@ -1841,6 +2216,15 @@ } OB += ">"; } + + friend bool operator==(SubobjectExpr const& LHS, + SubobjectExpr const& RHS) { + return LHS.Offset == RHS.Offset + && LHS.OnePastTheEnd == RHS.OnePastTheEnd + && LHS.Type->equals(RHS.Type) + && LHS.SubExpr->equals(RHS.SubExpr) + && LHS.UnionSelectors == RHS.UnionSelectors; + } }; class EnclosingExpr : public Node { @@ -1864,6 +2248,13 @@ OB.printClose(); OB += Postfix; } + + friend bool operator==(EnclosingExpr const& LHS, + EnclosingExpr const& RHS) { + return LHS.Prefix == RHS.Prefix + && LHS.Postfix == RHS.Postfix + && LHS.Infix->equals(RHS.Infix); + } }; class CastExpr : public Node { @@ -1892,6 +2283,13 @@ From->printAsOperand(OB); OB.printClose(); } + + friend bool operator==(CastExpr const& LHS, + CastExpr const& RHS) { + return LHS.CastKind == RHS.CastKind + && LHS.To->equals(RHS.To) + && LHS.From->equals(RHS.From); + } }; class SizeofParamPackExpr : public Node { @@ -1910,6 +2308,11 @@ PPE.printLeft(OB); OB.printClose(); } + + friend bool operator==(SizeofParamPackExpr const& LHS, + SizeofParamPackExpr const& RHS) { + return LHS.Pack->equals(RHS.Pack); + } }; class CallExpr : public Node { @@ -1930,6 +2333,12 @@ Args.printWithComma(OB); OB.printClose(); } + + friend bool operator==(CallExpr const& LHS, + CallExpr const& RHS) { + return LHS.Callee->equals(RHS.Callee) + && LHS.Args == RHS.Args; + } }; class NewExpr : public Node { @@ -1968,6 +2377,15 @@ OB.printClose(); } } + + friend bool operator==(NewExpr const& LHS, + NewExpr const& RHS) { + return LHS.IsGlobal == RHS.IsGlobal + && LHS.IsArray == RHS.IsArray + && LHS.Type->equals(RHS.Type) + && LHS.ExprList == RHS.ExprList + && LHS.InitList == RHS.InitList; + } }; class DeleteExpr : public Node { @@ -1993,6 +2411,13 @@ OB += ' '; Op->print(OB); } + + friend bool operator==(DeleteExpr const& LHS, + DeleteExpr const& RHS) { + return LHS.IsGlobal == RHS.IsGlobal + && LHS.IsArray == RHS.IsArray + && LHS.Op->equals(RHS.Op); + } }; class PrefixExpr : public Node { @@ -2011,6 +2436,12 @@ OB += Prefix; Child->printAsOperand(OB, getPrecedence()); } + + friend bool operator==(PrefixExpr const& LHS, + PrefixExpr const& RHS) { + return LHS.Prefix == RHS.Prefix + && LHS.Child->equals(RHS.Child); + } }; class FunctionParam : public Node { @@ -2025,6 +2456,11 @@ OB += "fp"; OB += Number; } + + friend bool operator==(FunctionParam const& LHS, + FunctionParam const& RHS) { + return LHS.Number == RHS.Number; + } }; class ConversionExpr : public Node { @@ -2047,6 +2483,12 @@ Expressions.printWithComma(OB); OB.printClose(); } + + friend bool operator==(ConversionExpr const& LHS, + ConversionExpr const& RHS) { + return LHS.Type->equals(RHS.Type) + && LHS.Expressions == RHS.Expressions; + } }; class PointerToMemberConversionExpr : public Node { @@ -2072,6 +2514,13 @@ SubExpr->print(OB); OB.printClose(); } + + friend bool operator==(PointerToMemberConversionExpr const& LHS, + PointerToMemberConversionExpr const& RHS) { + return LHS.Offset == RHS.Offset + && LHS.Type->equals(RHS.Type) + && LHS.SubExpr->equals(RHS.SubExpr); + } }; class InitListExpr : public Node { @@ -2090,6 +2539,18 @@ Inits.printWithComma(OB); OB += '}'; } + + friend bool operator==(InitListExpr const& LHS, + InitListExpr const& RHS) { + if (!!LHS.Ty != !!RHS.Ty) + return false; + + if (LHS.Ty) + if (!LHS.Ty->equals(RHS.Ty)) + return false; + + return LHS.Inits == RHS.Inits; + } }; class BracedExpr : public Node { @@ -2115,6 +2576,13 @@ OB += " = "; Init->print(OB); } + + friend bool operator==(BracedExpr const& LHS, + BracedExpr const& RHS) { + return LHS.IsArray == RHS.IsArray + && LHS.Elem->equals(RHS.Elem) + && LHS.Init->equals(RHS.Init); + } }; class BracedRangeExpr : public Node { @@ -2137,6 +2605,13 @@ OB += " = "; Init->print(OB); } + + friend bool operator==(BracedRangeExpr const& LHS, + BracedRangeExpr const& RHS) { + return LHS.First->equals(RHS.First) + && LHS.Last->equals(RHS.Last) + && LHS.Init->equals(RHS.Init); + } }; class FoldExpr : public Node { @@ -2184,6 +2659,22 @@ } OB.printClose(); } + + friend bool operator==(FoldExpr const& LHS, + FoldExpr const& RHS) { + if (LHS.IsLeftFold != RHS.IsLeftFold + || LHS.OperatorName == RHS.OperatorName) + return false; + + if (!!LHS.Pack != !!RHS.Pack) + return false; + + if (LHS.Pack) + if (!LHS.Pack->equals(RHS.Pack)) + return false; + + return LHS.Init->equals(RHS.Init); + } }; class ThrowExpr : public Node { @@ -2198,6 +2689,11 @@ OB += "throw "; Op->print(OB); } + + friend bool operator==(ThrowExpr const& LHS, + ThrowExpr const& RHS) { + return LHS.Op->equals(RHS.Op); + } }; class BoolExpr : public Node { @@ -2211,6 +2707,11 @@ void printLeft(OutputBuffer &OB) const override { OB += Value ? StringView("true") : StringView("false"); } + + friend bool operator==(BoolExpr const& LHS, + BoolExpr const& RHS) { + return LHS.Value == RHS.Value; + } }; class StringLiteral : public Node { @@ -2226,6 +2727,11 @@ Type->print(OB); OB += ">\""; } + + friend bool operator==(StringLiteral const& LHS, + StringLiteral const& RHS) { + return LHS.Type->equals(RHS.Type); + } }; class LambdaExpr : public Node { @@ -2242,6 +2748,11 @@ static_cast(Type)->printDeclarator(OB); OB += "{...}"; } + + friend bool operator==(LambdaExpr const& LHS, + LambdaExpr const& RHS) { + return LHS.Type->equals(RHS.Type); + } }; class EnumLiteral : public Node { @@ -2265,6 +2776,12 @@ else OB << Integer; } + + friend bool operator==(EnumLiteral const& LHS, + EnumLiteral const& RHS) { + return LHS.Integer == RHS.Integer + && LHS.Ty->equals(RHS.Ty); + } }; class IntegerLiteral : public Node { @@ -2293,6 +2810,12 @@ if (Type.size() <= 3) OB += Type; } + + friend bool operator==(IntegerLiteral const& LHS, + IntegerLiteral const& RHS) { + return LHS.Type == RHS.Type + && LHS.Value == RHS.Value; + } }; template struct FloatData; @@ -2350,6 +2873,11 @@ OB += StringView(num, num + n); } } + + friend bool operator==(FloatLiteralImpl const& LHS, + FloatLiteralImpl const& RHS) { + return LHS.Contents == RHS.Contents; + } }; using FloatLiteral = FloatLiteralImpl; diff --git a/llvm/lib/Demangle/ItaniumDemangle.cpp b/llvm/lib/Demangle/ItaniumDemangle.cpp --- a/llvm/lib/Demangle/ItaniumDemangle.cpp +++ b/llvm/lib/Demangle/ItaniumDemangle.cpp @@ -58,6 +58,22 @@ return first; } +bool Node::equals(Node const* Other) const { + assert(Other != nullptr); + + if (K != Other->getKind()) + return false; + + switch (K) { +#define NODE(X) \ + case K##X: \ + return *static_cast(this) == *static_cast(Other); +#include "llvm/Demangle/ItaniumNodes.def" + } + assert(0 && "unknown mangling node kind"); +} + + #ifndef NDEBUG namespace { struct DumpVisitor { diff --git a/llvm/unittests/Demangle/ItaniumDemangleTest.cpp b/llvm/unittests/Demangle/ItaniumDemangleTest.cpp --- a/llvm/unittests/Demangle/ItaniumDemangleTest.cpp +++ b/llvm/unittests/Demangle/ItaniumDemangleTest.cpp @@ -7,32 +7,19 @@ //===----------------------------------------------------------------------===// #include "llvm/Demangle/ItaniumDemangle.h" +#include "ItaniumDemangleTestUtils.h" +#include "llvm/IR/Argument.h" #include "llvm/Support/Allocator.h" #include "gmock/gmock.h" #include "gtest/gtest.h" +#include #include +#include #include using namespace llvm; using namespace llvm::itanium_demangle; - -namespace { -class TestAllocator { - BumpPtrAllocator Alloc; - -public: - void reset() { Alloc.Reset(); } - - template T *makeNode(Args &&... args) { - return new (Alloc.Allocate(sizeof(T), alignof(T))) - T(std::forward(args)...); - } - - void *allocateNodeArray(size_t sz) { - return Alloc.Allocate(sizeof(Node *) * sz, alignof(Node *)); - } -}; -} // namespace +using namespace llvm::itanium_demangle::test_utils; namespace NodeMatcher { // Make sure the node matchers provide constructor parameters. This is a @@ -113,3 +100,162 @@ ASSERT_NE(nullptr, Parser.parse()); EXPECT_THAT(Parser.Types, testing::ElementsAre("_Float16", "A", "_Float16")); } + +TEST(ItaniumDemangle, Equality_NodeArray) { + ManglingNodeCreator Creator; + + // Test empty NodeArray equality + std::vector LHS; + std::vector RHS; + + // Empty == Empty + ASSERT_EQ(Creator.makeNodeArray(LHS.cbegin(), LHS.cend()), + Creator.makeNodeArray(RHS.cbegin(), RHS.cend())); + + RHS.push_back(Creator.makeReferenceType(Qualifiers::QualNone, "test", + ReferenceKind::RValue)); + + // Empty vs. non-empty + ASSERT_NE(Creator.makeNodeArray(LHS.cbegin(), LHS.cend()), + Creator.makeNodeArray(RHS.cbegin(), RHS.cend())); + + LHS.push_back(Creator.makeReferenceType(Qualifiers::QualNone, "test", + ReferenceKind::RValue)); + + // Equal single nodes + ASSERT_EQ(Creator.makeNodeArray(LHS.cbegin(), LHS.cend()), + Creator.makeNodeArray(RHS.cbegin(), RHS.cend())); + + LHS.push_back(Creator.makeReferenceType(Qualifiers::QualNone, "test", + ReferenceKind::LValue)); + RHS.push_back(Creator.makeReferenceType(Qualifiers::QualRestrict, "test", + ReferenceKind::RValue)); + + // Non-equal second node + ASSERT_NE(Creator.makeNodeArray(LHS.cbegin(), LHS.cend()), + Creator.makeNodeArray(RHS.cbegin(), RHS.cend())); +} + +TEST(ItaniumDemangle, Equality_QualType) { + ManglingNodeCreator Creator; + + { + // Same qualifiers and name + Node const *Q1 = Creator.makeQualType("Test", Qualifiers::QualVolatile); + Node const *Q2 = Creator.makeQualType("Test", Qualifiers::QualVolatile); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Different qualifiers + Node const *Q1 = Creator.makeQualType("Test", Qualifiers::QualNone); + Node const *Q2 = Creator.makeQualType("Test", Qualifiers::QualRestrict); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Different name + Node const *Q1 = Creator.makeQualType("Test", Qualifiers::QualNone); + Node const *Q2 = Creator.makeQualType("", Qualifiers::QualNone); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } +} + +TEST(ItaniumDemangle, Equality_NameType) { + ManglingNodeCreator Creator; + + { + // Both empty + Node const *Q1 = Creator.makeNameType(""); + Node const *Q2 = Creator.makeNameType(""); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Both non-empty + Node const *Q1 = Creator.makeNameType("test"); + Node const *Q2 = Creator.makeNameType("test"); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Not equal + Node const *Q1 = Creator.makeNameType("test"); + Node const *Q2 = Creator.makeNameType("tes"); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } +} + +TEST(ItaniumDemangle, Equality_ReferenceType) { + ManglingNodeCreator Creator; + + { + // Same type + Node const *Q1 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::LValue); + Node const *Q2 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::LValue); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Different name + Node const *Q1 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::LValue); + Node const *Q2 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Tes", + ReferenceKind::LValue); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Different CV-qualifiers + Node const *Q1 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::LValue); + Node const *Q2 = Creator.makeReferenceType(Qualifiers::QualRestrict, "Test", + ReferenceKind::LValue); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } + + { + // Different ref-qualifiers + Node const *Q1 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::LValue); + Node const *Q2 = Creator.makeReferenceType(Qualifiers::QualVolatile, "Test", + ReferenceKind::RValue); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } +} + +TEST(ItaniumDemangle, Equality_TemplateArgs) { + ManglingNodeCreator Creator; + + std::vector LHS; + std::vector RHS; + + { + // Both empty + Node const *Q1 = Creator.makeTemplateArgs(LHS); + Node const *Q2 = Creator.makeTemplateArgs(RHS); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + LHS.push_back(Creator.makeNameType("test")); + RHS.push_back(Creator.makeNameType("test")); + + { + // Both equal + Node const *Q1 = Creator.makeTemplateArgs(LHS); + Node const *Q2 = Creator.makeTemplateArgs(RHS); + ASSERT_TRUE(test_utils::compareNodes(Q1, Q2)); + } + + LHS.push_back(Creator.makeNameType("foo")); + RHS.push_back(Creator.makeNameType("bar")); + + { + // Not equal anymore + Node const *Q1 = Creator.makeTemplateArgs(LHS); + Node const *Q2 = Creator.makeTemplateArgs(RHS); + ASSERT_FALSE(test_utils::compareNodes(Q1, Q2)); + } +} diff --git a/llvm/unittests/Demangle/ItaniumDemangleTestUtils.h b/llvm/unittests/Demangle/ItaniumDemangleTestUtils.h new file mode 100644 --- /dev/null +++ b/llvm/unittests/Demangle/ItaniumDemangleTestUtils.h @@ -0,0 +1,77 @@ +//===------------------ ItaniumDemangleTestUtils.h ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEMANGLE_ITANIUMDEMANGLE_TEST_UTILS_H +#define LLVM_DEMANGLE_ITANIUMDEMANGLE_TEST_UTILS_H + +#include "llvm/Demangle/Demangle.h" +#include "llvm/Demangle/ItaniumDemangle.h" +#include "llvm/Demangle/StringView.h" +#include "llvm/Support/Allocator.h" + +#include + +namespace llvm::itanium_demangle::test_utils { + +class TestAllocator { + BumpPtrAllocator Alloc; + +public: + void reset() { Alloc.Reset(); } + + template T *makeNode(Args &&...args) { + return new (Alloc.Allocate(sizeof(T), alignof(T))) + T(std::forward(args)...); + } + + void *allocateNodeArray(size_t sz) { + return Alloc.Allocate(sizeof(Node *) * sz, alignof(Node *)); + } +}; + +struct ManglingNodeCreator + : AbstractManglingParser { + + ManglingNodeCreator() : AbstractManglingParser(nullptr, nullptr) {} + + auto *makeNameType(StringView Type) { return make(Type); } + + auto *makeTemplateArgs(std::vector const &Args) { + return make(makeNodeArray(Args.cbegin(), Args.cend())); + } + + auto *makeQualType(StringView VarName, Qualifiers Quals) { + return make(makeNameType(VarName), Quals); + } + + auto *makeReferenceType(Qualifiers Quals, StringView ArgName, + ReferenceKind RefKind) { + return make(makeQualType(ArgName, Quals), RefKind); + } + + auto *makeNameWithTemplateArgsNode(StringView FnName, + std::vector const &Args) { + auto *TArgs = makeTemplateArgs(Args); + return make(makeNameType(FnName), TArgs); + } + + auto *makeFunctionEncoding(StringView FnName, NodeArray Params, + Qualifiers CVQuals, FunctionRefQual RefQual) { + auto const *NameNode = makeNameType(FnName); + return make(nullptr, NameNode, Params, nullptr, CVQuals, + RefQual); + } +}; + +inline bool compareNodes(Node const *LHS, Node const *RHS) { + return LHS && RHS && LHS->equals(RHS); +} + +} // namespace llvm::itanium_demangle::test_utils + +#endif // LLVM_DEMANGLE_ITANIUMDEMANGLE_TEST_UTILS_H