[libcxx-commits] [clang] [libcxxabi] [llvm] [Clang] Mangling of pack indexing type and expression for itanium (PR #123513)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Jan 26 20:32:22 PST 2025
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/123513
>From ca55a3fd1ca8e7d87758b7eda8f0d813e1bee2ce Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Sun, 19 Jan 2025 15:08:52 +0100
Subject: [PATCH 1/2] [Clang] Mangling of pack indexing type and expression for
itanium
---
clang/docs/ReleaseNotes.rst | 1 +
clang/lib/AST/ItaniumMangle.cpp | 35 ++++++++--------
clang/test/CodeGenCXX/mangle-cxx2c.cpp | 11 +++++
libcxxabi/src/demangle/ItaniumDemangle.h | 43 ++++++++++++++++++++
libcxxabi/src/demangle/ItaniumNodes.def | 2 +-
libcxxabi/test/test_demangle.pass.cpp | 5 +++
llvm/include/llvm/Demangle/ItaniumDemangle.h | 43 ++++++++++++++++++++
llvm/include/llvm/Demangle/ItaniumNodes.def | 2 +-
8 files changed, 124 insertions(+), 18 deletions(-)
create mode 100644 clang/test/CodeGenCXX/mangle-cxx2c.cpp
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index b63bd366cfe884..e5946fc71c56a6 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1003,6 +1003,7 @@ Bug Fixes to C++ Support
lambda functions or inline friend functions defined inside templates (#GH122493).
- Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423)
- Correctly determine the implicit constexprness of lambdas in dependent contexts. (#GH97958) (#GH114234)
+- Implement Itanium mangling for pack indexing. (#GH112003)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 1dd936cf4fb518..077fbf57e43c1c 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,10 +4349,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) {
@@ -4787,6 +4788,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>
@@ -4806,6 +4808,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
@@ -4815,6 +4819,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
@@ -4886,7 +4891,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 +5792,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 +5822,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";
diff --git a/clang/test/CodeGenCXX/mangle-cxx2c.cpp b/clang/test/CodeGenCXX/mangle-cxx2c.cpp
new file mode 100644
index 00000000000000..3e4689948a7a7e
--- /dev/null
+++ b/clang/test/CodeGenCXX/mangle-cxx2c.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-linux-gnu -std=c++2a | FileCheck %s
+
+namespace spaceship {
+ struct X {};
+ struct Y {};
+ int operator<=>(X, Y);
+
+ // CHECK-LABEL: define {{.*}} @_ZN9spaceship1fIiEEvDTcmltcvNS_1YE_EcvNS_1XE_EcvT__EE
+ template<typename T> void f(decltype(Y() < X(), T()) x) {}
+ template void f<int>(int);
+}
diff --git a/libcxxabi/src/demangle/ItaniumDemangle.h b/libcxxabi/src/demangle/ItaniumDemangle.h
index 3df41b5f4d7d07..4cda6514bfac35 100644
--- a/libcxxabi/src/demangle/ItaniumDemangle.h
+++ b/libcxxabi/src/demangle/ItaniumDemangle.h
@@ -1521,6 +1521,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('[');
+ Index->printLeft(OB);
+ OB.printClose(']');
+ }
+};
+
class TemplateArgs final : public Node {
NodeArray Params;
Node *Requires;
@@ -4510,6 +4531,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 +5387,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 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..f567bfea37dbc8 100644
--- a/llvm/include/llvm/Demangle/ItaniumDemangle.h
+++ b/llvm/include/llvm/Demangle/ItaniumDemangle.h
@@ -1521,6 +1521,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('[');
+ Index->printLeft(OB);
+ OB.printClose(']');
+ }
+};
+
class TemplateArgs final : public Node {
NodeArray Params;
Node *Requires;
@@ -4510,6 +4531,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 +5387,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 330552663ee658..3a28b1f1759247 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
>From f17310f2c62a17f937aa90444b7087f0b5696606 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 27 Jan 2025 05:32:06 +0100
Subject: [PATCH 2/2] Fix test file
---
clang/test/CodeGenCXX/mangle-cxx2c.cpp | 39 ++++++++++++++++++++------
1 file changed, 31 insertions(+), 8 deletions(-)
diff --git a/clang/test/CodeGenCXX/mangle-cxx2c.cpp b/clang/test/CodeGenCXX/mangle-cxx2c.cpp
index 3e4689948a7a7e..30bba7ae625493 100644
--- a/clang/test/CodeGenCXX/mangle-cxx2c.cpp
+++ b/clang/test/CodeGenCXX/mangle-cxx2c.cpp
@@ -1,11 +1,34 @@
-// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-linux-gnu -std=c++2a | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-linux-gnu -std=c++2c | FileCheck %s
-namespace spaceship {
- struct X {};
- struct Y {};
- int operator<=>(X, Y);
+namespace GH112003 {
- // CHECK-LABEL: define {{.*}} @_ZN9spaceship1fIiEEvDTcmltcvNS_1YE_EcvNS_1XE_EcvT__EE
- template<typename T> void f(decltype(Y() < X(), T()) x) {}
- template void f<int>(int);
+// 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);
+}
}
More information about the libcxx-commits
mailing list