https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/123513
None >From 1b016f8b86eb004568e2779d19cc030e8c487762 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Sun, 19 Jan 2025 15:08:52 +0100 Subject: [PATCH] [WIP][Clang] Mangling of pack indexing type and expression for itanium --- clang/lib/AST/ItaniumMangle.cpp | 47 +++++++++++++------ libcxxabi/src/demangle/ItaniumDemangle.h | 44 ++++++++++++++++++ libcxxabi/src/demangle/ItaniumNodes.def | 2 +- libcxxabi/test/test_demangle.pass.cpp | 5 ++ llvm/include/llvm/Demangle/ItaniumDemangle.h | 49 ++++++++++++++++++++ llvm/include/llvm/Demangle/ItaniumNodes.def | 1 + 6 files changed, 134 insertions(+), 14 deletions(-) diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 1dd936cf4fb518..e8709425394e5c 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -603,6 +603,7 @@ class CXXNameMangler { void mangleInitListElements(const InitListExpr *InitList); void mangleRequirement(SourceLocation RequiresExprLoc, const concepts::Requirement *Req); + void mangleReferenceToPack(const NamedDecl* ND); void mangleExpression(const Expr *E, unsigned Arity = UnknownArity, bool AsTemplateArg = false); void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom); @@ -4348,8 +4349,12 @@ void CXXNameMangler::mangleType(const PackExpansionType *T) { } void CXXNameMangler::mangleType(const PackIndexingType *T) { - if (!T->hasSelectedType()) + // <type> ::= Dy <type> <expression> # pack indexing type (C++23) + if (!T->hasSelectedType()) { + Out << "Dy"; mangleType(T->getPattern()); + mangleExpression(T->getIndexExpr()); + } else mangleType(T->getSelectedType()); } @@ -4785,6 +4790,19 @@ void CXXNameMangler::mangleRequirement(SourceLocation RequiresExprLoc, } } +void CXXNameMangler::mangleReferenceToPack(const NamedDecl* Pack) { + if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack)) + mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); + else if (const NonTypeTemplateParmDecl *NTTP + = dyn_cast<NonTypeTemplateParmDecl>(Pack)) + mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex()); + else if (const TemplateTemplateParmDecl *TempTP + = dyn_cast<TemplateTemplateParmDecl>(Pack)) + mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex()); + else + mangleFunctionParam(cast<ParmVarDecl>(Pack)); +} + void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, bool AsTemplateArg) { // <expression> ::= <unary operator-name> <expression> @@ -4803,6 +4821,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, // ::= fpT # 'this' expression (part of <function-param>) // ::= sr <type> <unqualified-name> # dependent name // ::= sr <type> <unqualified-name> <template-args> # dependent template-id + // ::= sy <expression> <expression> # pack indexing expression // ::= ds <expression> <expression> # expr.*expr // ::= sZ <template-param> # size of a parameter pack // ::= sZ <function-param> # size of a function parameter pack @@ -4886,7 +4905,6 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, case Expr::OMPIteratorExprClass: case Expr::CXXInheritedCtorInitExprClass: case Expr::CXXParenListInitExprClass: - case Expr::PackIndexingExprClass: llvm_unreachable("unexpected statement kind"); case Expr::ConstantExprClass: @@ -5788,17 +5806,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, } Out << "sZ"; - const NamedDecl *Pack = SPE->getPack(); - if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack)) - mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); - else if (const NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(Pack)) - mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex()); - else if (const TemplateTemplateParmDecl *TempTP - = dyn_cast<TemplateTemplateParmDecl>(Pack)) - mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex()); - else - mangleFunctionParam(cast<ParmVarDecl>(Pack)); + mangleReferenceToPack(SPE->getPack()); break; } @@ -5828,6 +5836,19 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, break; } + case Expr::PackIndexingExprClass: { + auto *PE = cast<PackIndexingExpr>(E); + if(PE->isFullySubstituted()) { + E = PE->getSelectedExpr(); + goto recurse; + } + NotPrimaryExpr(); + Out << "sy"; + mangleReferenceToPack(PE->getPackDecl()); + mangleExpression(PE->getIndexExpr()); + break; + } + case Expr::CXXThisExprClass: NotPrimaryExpr(); Out << "fpT"; diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index 3df41b5f4d7d07..a65de9fee4a208 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -1521,6 +1521,29 @@ class ParameterPackExpansion final : public Node { } }; +class PackIndexing final : public Node { + const Node *Pattern; + const Node *Index; + +public: + PackIndexing(const Node *Pattern_, const Node *Index_) + : Node(KPackIndexing), Pattern(Pattern_), Index(Index_) {} + + template <typename Fn> void match(Fn F) const { + F(Pattern, Index); + } + + void printLeft(OutputBuffer &OB) const override { + OB.printOpen('('); + ParameterPackExpansion PPE(Pattern); + PPE.printLeft(OB); + OB.printClose(')'); + OB.printOpen('['); + Index->printLeft(OB); + OB.printClose(']'); + } +}; + class TemplateArgs final : public Node { NodeArray Params; Node *Requires; @@ -4510,6 +4533,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { Result = make<ParameterPackExpansion>(Child); break; } + // ::= Dy <type> <expression> # pack indexing (C++26) + case 'y': { + First += 2; + Node *Pattern = getDerived().parseType(); + if (!Pattern) + return nullptr; + Node *Index = getDerived().parseExpr(); + if (!Index) + return nullptr; + Result = make<PackIndexing>(Pattern, Index); + break; + } // Exception specifier on a function type. case 'o': case 'O': @@ -5354,6 +5389,15 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { return nullptr; return make<ParameterPackExpansion>(Child); } + if (consumeIf("sy")) { + Node *Pattern = getDerived().parseExpr(); + if (Pattern == nullptr) + return nullptr; + Node *Index = getDerived().parseExpr(); + if (Index == nullptr) + return nullptr; + return make<PackIndexing>(Pattern, Index); + } if (consumeIf("sZ")) { if (look() == 'T') { Node *R = getDerived().parseTemplateParam(); diff --git a/libcxxabi/src/demangle/ItaniumNodes.def b/libcxxabi/src/demangle/ItaniumNodes.def index 18f5d52b47e911..2c183ec5d23f86 100644 --- a/libcxxabi/src/demangle/ItaniumNodes.def +++ b/libcxxabi/src/demangle/ItaniumNodes.def @@ -100,5 +100,5 @@ NODE(ExprRequirement) NODE(TypeRequirement) NODE(NestedRequirement) NODE(ExplicitObjectParameter) - +NODE(PackIndexing) #undef NODE diff --git a/libcxxabi/test/test_demangle.pass.cpp b/libcxxabi/test/test_demangle.pass.cpp index e9c74f70a094b5..e0a84de5e8cef9 100644 --- a/libcxxabi/test/test_demangle.pass.cpp +++ b/libcxxabi/test/test_demangle.pass.cpp @@ -30220,6 +30220,11 @@ const char* cases[][2] = { {"_ZZNH3Foo3fooES_iENK4Foo24foo2Ev", "Foo::foo(this Foo, int)::Foo2::foo2() const" }, {"_ZNH3FooclERKS_", "Foo::operator()(this Foo const&)"}, + + // C++26 pack indexing + {"_Z3fooILi0ETpTnDaJLi1ELi2EEEDTsyT0_T_Ev", "decltype((1, 2...)[0]) foo<0, 1, 2>()"}, + {"_Z1gILi0EJciEEDyT0_T_v", "(char, int)[0] g<0, char, int>()"}, + // fixed-point types as defined in the N1169 draft of ISO/IEC DTR 18037 {"_Z1fDAs", "f(short _Accum)"}, {"_Z1fDAt", "f(unsigned short _Accum)"}, diff --git a/llvm/include/llvm/Demangle/ItaniumDemangle.h b/llvm/include/llvm/Demangle/ItaniumDemangle.h index b0363c1a7a7863..e62de5d06a7c2a 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -1521,6 +1521,30 @@ class ParameterPackExpansion final : public Node { } }; +/// A pack expansion. Below this node, there are some unexpanded ParameterPacks +/// which each have Child->ParameterPackSize elements. +class PackIndexing final : public Node { + const Node *Pattern; + const Node *Index; + +public: + PackIndexing(const Node *Pattern_, const Node *Index_) + : Node(KPackIndexing), Pattern(Pattern_), Index(Index_) {} + + template <typename Fn> void match(Fn F) const { + F(Pattern, Index); + } + + void printLeft(OutputBuffer &OB) const override { + ParameterPackExpansion PPE(Pattern); + PPE.printLeft(OB); + OB += "...["; + Index->print(OB); + OB += "]"; + } +}; + + class TemplateArgs final : public Node { NodeArray Params; Node *Requires; @@ -4510,6 +4534,20 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() { Result = make<ParameterPackExpansion>(Child); break; } + // ::= Dy <type> <expression> # pack indexing (C++26) + case 'y': { + First += 2; + Node *Pattern = look() == 'T' ? + getDerived().parseTemplateParam() + : getDerived().parseFunctionParam(); + if (Pattern == nullptr) + return nullptr; + Node *Index = getDerived().parseExpr(); + if (Index == nullptr) + return nullptr; + Result = make<PackIndexing>(Pattern, Index); + break; + } // Exception specifier on a function type. case 'o': case 'O': @@ -5354,6 +5392,17 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() { return nullptr; return make<ParameterPackExpansion>(Child); } + if (consumeIf("sy")) { + Node *Pattern = look() == 'T' ? + getDerived().parseTemplateParam() + : getDerived().parseFunctionParam(); + if (Pattern == nullptr) + return nullptr; + Node *Index = getDerived().parseExpr(); + if (Index == nullptr) + return nullptr; + return make<PackIndexing>(Pattern, Index); + } if (consumeIf("sZ")) { if (look() == 'T') { Node *R = getDerived().parseTemplateParam(); diff --git a/llvm/include/llvm/Demangle/ItaniumNodes.def b/llvm/include/llvm/Demangle/ItaniumNodes.def index 330552663ee658..4108c4839e6db5 100644 --- a/llvm/include/llvm/Demangle/ItaniumNodes.def +++ b/llvm/include/llvm/Demangle/ItaniumNodes.def @@ -100,5 +100,6 @@ NODE(ExprRequirement) NODE(TypeRequirement) NODE(NestedRequirement) NODE(ExplicitObjectParameter) +NODE(PackIndexing) #undef NODE _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits