Author: Corentin Jabot Date: 2026-05-15T16:50:30+02:00 New Revision: 68e8dd698dc6ac96f26d9144bd3117f2bc6bca49
URL: https://github.com/llvm/llvm-project/commit/68e8dd698dc6ac96f26d9144bd3117f2bc6bca49 DIFF: https://github.com/llvm/llvm-project/commit/68e8dd698dc6ac96f26d9144bd3117f2bc6bca49.diff LOG: [Clang] Mangling of pack indexing type and expression for itanium (#123513) See https://github.com/itanium-cxx-abi/cxx-abi/pull/198 and #112003 Added: clang/test/CodeGenCXX/mangle-cxx2c.cpp Modified: clang/docs/ReleaseNotes.rst clang/lib/AST/ItaniumMangle.cpp libcxxabi/src/demangle/ItaniumDemangle.h libcxxabi/src/demangle/ItaniumNodes.def libcxxabi/test/DemangleTestCases.inc llvm/include/llvm/Demangle/ItaniumDemangle.h llvm/include/llvm/Demangle/ItaniumNodes.def llvm/include/llvm/Testing/Demangle/DemangleTestCases.inc Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index c54b6e5a1757e..f5660f9670eae 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -155,6 +155,8 @@ C++2c Feature Support C++23 Feature Support ^^^^^^^^^^^^^^^^^^^^^ +- Partially implement Itanium mangling for pack indexing. Partially substituted packs are not yet supported. (#GH112003) + C++20 Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 7ff9513dbe6ef..4f9ba1ccd4f79 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -593,6 +593,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); @@ -4430,10 +4431,10 @@ void CXXNameMangler::mangleType(const PackExpansionType *T) { } void CXXNameMangler::mangleType(const PackIndexingType *T) { - if (!T->hasSelectedType()) - mangleType(T->getPattern()); - else - mangleType(T->getSelectedType()); + // <type> ::= Dy <type> <expression> # pack indexing type (C++23) + Out << "Dy"; + mangleType(T->getPattern()); + mangleExpression(T->getIndexExpr()); } void CXXNameMangler::mangleType(const ObjCInterfaceType *T) { @@ -4899,6 +4900,7 @@ void CXXNameMangler::mangleRequirement(SourceLocation RequiresExprLoc, void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, bool AsTemplateArg) { + // clang-format off // <expression> ::= <unary operator-name> <expression> // ::= <binary operator-name> <expression> <expression> // ::= <trinary operator-name> <expression> <expression> <expression> @@ -4918,6 +4920,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, // ::= ds <expression> <expression> # expr.*expr // ::= sZ <template-param> # size of a parameter pack // ::= sZ <function-param> # size of a function parameter pack + // ::= sy <template-param> <expression> # pack indexing expression + // ::= sy <function-param> <expression> # pack indexing expression // ::= u <source-name> <template-arg>* E # vendor extended expression // ::= <expr-primary> // <expr-primary> ::= L <type> <value number> E # integer literal @@ -4927,6 +4931,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, // ::= L <pointer type> 0 E # null pointer template argument // ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C99); not used by clang // ::= L <mangled-name> E # external name + // clang-format on QualType ImplicitlyConvertedToType; // A top-level expression that's not <expr-primary> needs to be wrapped in @@ -4997,7 +5002,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: @@ -5891,17 +5895,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; } @@ -5931,6 +5925,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, break; } + case Expr::PackIndexingExprClass: { + auto *PE = cast<PackIndexingExpr>(E); + NotPrimaryExpr(); + Out << "sy"; + mangleReferenceToPack(PE->getPackDecl()); + mangleExpression(PE->getIndexExpr()); + break; + } + case Expr::CXXThisExprClass: NotPrimaryExpr(); Out << "fpT"; @@ -6112,6 +6115,17 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) { } } +void CXXNameMangler::mangleReferenceToPack(const NamedDecl *Pack) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Pack)) + mangleTemplateParameter(TTP->getDepth(), TTP->getIndex()); + else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(Pack)) + mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex()); + else if (const auto *TempTP = dyn_cast<TemplateTemplateParmDecl>(Pack)) + mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex()); + else + mangleFunctionParam(cast<ParmVarDecl>(Pack)); +} + // Helper to provide ancillary information on a template used to mangle its // arguments. struct CXXNameMangler::TemplateArgManglingInfo { diff --git a/clang/test/CodeGenCXX/mangle-cxx2c.cpp b/clang/test/CodeGenCXX/mangle-cxx2c.cpp new file mode 100644 index 0000000000000..1dd5c7e4af264 --- /dev/null +++ b/clang/test/CodeGenCXX/mangle-cxx2c.cpp @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=%itanium_abi_triple -std=c++2c | FileCheck %s + +namespace GH112003 { + +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033fooILi0ETpTnDaJLi0ELi0EEEEDTsyT0_T_Ev +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033fooILi1ETpTnDaJLi0ELi0EEEEDTsyT0_T_Ev +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033fooILi0ETpTnDaJLl1EEEEDTsyT0_T_Ev +template <int I, auto...V> +decltype(V...[I]) foo() {return {};} + +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033barILi0EJilEEEDyT0_T_v +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033barILi1EJilEEEDyT0_T_v +template <int I, typename...V> +V...[I] bar() {return {};} + + +template <int I, typename... T> +using First = T...[0]; + +// CHECK-LABEL: define {{.*}} @_ZN8GH1120033bazILi0EJiEEEvDy_SUBSTPACK_Li0E +// FIXME: handle indexing of partially substituted packs +template <int I, typename...V> +void baz(First<I, int, V...>){}; + + +void fn() { + foo<0, 0, 0>(); + foo<1, 0, 0>(); + foo<0, 1L>(); + bar<0, int, long>(); + bar<1, int, long>(); + baz<0, int>(0); +} +} diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h index c001a8d33f227..94d780e229631 100644 --- a/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/libcxxabi/src/demangle/ItaniumDemangle.h @@ -1537,6 +1537,27 @@ 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('['); + OB.printLeft(*Index); + OB.printClose(']'); + } +}; + class TemplateArgs final : public Node { NodeArray Params; Node *Requires; @@ -4531,6 +4552,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': @@ -5375,6 +5408,16 @@ 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/libcxxabi/src/demangle/ItaniumNodes.def b/libcxxabi/src/demangle/ItaniumNodes.def index 18f5d52b47e91..2c183ec5d23f8 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/DemangleTestCases.inc b/libcxxabi/test/DemangleTestCases.inc index 307d0a8c02a41..6b7a99d849a94 100644 --- a/libcxxabi/test/DemangleTestCases.inc +++ b/libcxxabi/test/DemangleTestCases.inc @@ -30187,6 +30187,10 @@ {"_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 6d7f189a6e44c..04338e1d7cb51 100644 --- a/llvm/include/llvm/Demangle/ItaniumDemangle.h +++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h @@ -1537,6 +1537,27 @@ 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('['); + OB.printLeft(*Index); + OB.printClose(']'); + } +}; + class TemplateArgs final : public Node { NodeArray Params; Node *Requires; @@ -4531,6 +4552,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': @@ -5375,6 +5408,16 @@ 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 330552663ee65..3a28b1f175924 100644 --- a/llvm/include/llvm/Demangle/ItaniumNodes.def +++ b/llvm/include/llvm/Demangle/ItaniumNodes.def @@ -100,5 +100,5 @@ NODE(ExprRequirement) NODE(TypeRequirement) NODE(NestedRequirement) NODE(ExplicitObjectParameter) - +NODE(PackIndexing) #undef NODE diff --git a/llvm/include/llvm/Testing/Demangle/DemangleTestCases.inc b/llvm/include/llvm/Testing/Demangle/DemangleTestCases.inc index 307d0a8c02a41..6b7a99d849a94 100644 --- a/llvm/include/llvm/Testing/Demangle/DemangleTestCases.inc +++ b/llvm/include/llvm/Testing/Demangle/DemangleTestCases.inc @@ -30187,6 +30187,10 @@ {"_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)"}, _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
