Skip to content

Commit ca55a3f

Browse files
committed
[Clang] Mangling of pack indexing type and expression for itanium
1 parent e8e75e0 commit ca55a3f

File tree

8 files changed

+124
-18
lines changed

8 files changed

+124
-18
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,7 @@ Bug Fixes to C++ Support
10031003
lambda functions or inline friend functions defined inside templates (#GH122493).
10041004
- Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423)
10051005
- Correctly determine the implicit constexprness of lambdas in dependent contexts. (#GH97958) (#GH114234)
1006+
- Implement Itanium mangling for pack indexing. (#GH112003)
10061007

10071008
Bug Fixes to AST Handling
10081009
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,7 @@ class CXXNameMangler {
603603
void mangleInitListElements(const InitListExpr *InitList);
604604
void mangleRequirement(SourceLocation RequiresExprLoc,
605605
const concepts::Requirement *Req);
606+
void mangleReferenceToPack(const NamedDecl *ND);
606607
void mangleExpression(const Expr *E, unsigned Arity = UnknownArity,
607608
bool AsTemplateArg = false);
608609
void mangleCXXCtorType(CXXCtorType T, const CXXRecordDecl *InheritedFrom);
@@ -4348,10 +4349,10 @@ void CXXNameMangler::mangleType(const PackExpansionType *T) {
43484349
}
43494350

43504351
void CXXNameMangler::mangleType(const PackIndexingType *T) {
4351-
if (!T->hasSelectedType())
4352-
mangleType(T->getPattern());
4353-
else
4354-
mangleType(T->getSelectedType());
4352+
// <type> ::= Dy <type> <expression> # pack indexing type (C++23)
4353+
Out << "Dy";
4354+
mangleType(T->getPattern());
4355+
mangleExpression(T->getIndexExpr());
43554356
}
43564357

43574358
void CXXNameMangler::mangleType(const ObjCInterfaceType *T) {
@@ -4787,6 +4788,7 @@ void CXXNameMangler::mangleRequirement(SourceLocation RequiresExprLoc,
47874788

47884789
void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
47894790
bool AsTemplateArg) {
4791+
// clang-format off
47904792
// <expression> ::= <unary operator-name> <expression>
47914793
// ::= <binary operator-name> <expression> <expression>
47924794
// ::= <trinary operator-name> <expression> <expression> <expression>
@@ -4806,6 +4808,8 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
48064808
// ::= ds <expression> <expression> # expr.*expr
48074809
// ::= sZ <template-param> # size of a parameter pack
48084810
// ::= sZ <function-param> # size of a function parameter pack
4811+
// ::= sy <template-param> <expression> # pack indexing expression
4812+
// ::= sy <function-param> <expression> # pack indexing expression
48094813
// ::= u <source-name> <template-arg>* E # vendor extended expression
48104814
// ::= <expr-primary>
48114815
// <expr-primary> ::= L <type> <value number> E # integer literal
@@ -4815,6 +4819,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
48154819
// ::= L <pointer type> 0 E # null pointer template argument
48164820
// ::= L <type> <real-part float> _ <imag-part float> E # complex floating point literal (C99); not used by clang
48174821
// ::= L <mangled-name> E # external name
4822+
// clang-format on
48184823
QualType ImplicitlyConvertedToType;
48194824

48204825
// 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,
48864891
case Expr::OMPIteratorExprClass:
48874892
case Expr::CXXInheritedCtorInitExprClass:
48884893
case Expr::CXXParenListInitExprClass:
4889-
case Expr::PackIndexingExprClass:
48904894
llvm_unreachable("unexpected statement kind");
48914895

48924896
case Expr::ConstantExprClass:
@@ -5788,17 +5792,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
57885792
}
57895793

57905794
Out << "sZ";
5791-
const NamedDecl *Pack = SPE->getPack();
5792-
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
5793-
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
5794-
else if (const NonTypeTemplateParmDecl *NTTP
5795-
= dyn_cast<NonTypeTemplateParmDecl>(Pack))
5796-
mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex());
5797-
else if (const TemplateTemplateParmDecl *TempTP
5798-
= dyn_cast<TemplateTemplateParmDecl>(Pack))
5799-
mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex());
5800-
else
5801-
mangleFunctionParam(cast<ParmVarDecl>(Pack));
5795+
mangleReferenceToPack(SPE->getPack());
58025796
break;
58035797
}
58045798

@@ -5828,6 +5822,15 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
58285822
break;
58295823
}
58305824

5825+
case Expr::PackIndexingExprClass: {
5826+
auto *PE = cast<PackIndexingExpr>(E);
5827+
NotPrimaryExpr();
5828+
Out << "sy";
5829+
mangleReferenceToPack(PE->getPackDecl());
5830+
mangleExpression(PE->getIndexExpr());
5831+
break;
5832+
}
5833+
58315834
case Expr::CXXThisExprClass:
58325835
NotPrimaryExpr();
58335836
Out << "fpT";
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-linux-gnu -std=c++2a | FileCheck %s
2+
3+
namespace spaceship {
4+
struct X {};
5+
struct Y {};
6+
int operator<=>(X, Y);
7+
8+
// CHECK-LABEL: define {{.*}} @_ZN9spaceship1fIiEEvDTcmltcvNS_1YE_EcvNS_1XE_EcvT__EE
9+
template<typename T> void f(decltype(Y() < X(), T()) x) {}
10+
template void f<int>(int);
11+
}

libcxxabi/src/demangle/ItaniumDemangle.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,27 @@ class ParameterPackExpansion final : public Node {
15211521
}
15221522
};
15231523

1524+
class PackIndexing final : public Node {
1525+
const Node *Pattern;
1526+
const Node *Index;
1527+
1528+
public:
1529+
PackIndexing(const Node *Pattern_, const Node *Index_)
1530+
: Node(KPackIndexing), Pattern(Pattern_), Index(Index_) {}
1531+
1532+
template <typename Fn> void match(Fn F) const { F(Pattern, Index); }
1533+
1534+
void printLeft(OutputBuffer &OB) const override {
1535+
OB.printOpen('(');
1536+
ParameterPackExpansion PPE(Pattern);
1537+
PPE.printLeft(OB);
1538+
OB.printClose(')');
1539+
OB.printOpen('[');
1540+
Index->printLeft(OB);
1541+
OB.printClose(']');
1542+
}
1543+
};
1544+
15241545
class TemplateArgs final : public Node {
15251546
NodeArray Params;
15261547
Node *Requires;
@@ -4510,6 +4531,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
45104531
Result = make<ParameterPackExpansion>(Child);
45114532
break;
45124533
}
4534+
// ::= Dy <type> <expression> # pack indexing (C++26)
4535+
case 'y': {
4536+
First += 2;
4537+
Node *Pattern = getDerived().parseType();
4538+
if (!Pattern)
4539+
return nullptr;
4540+
Node *Index = getDerived().parseExpr();
4541+
if (!Index)
4542+
return nullptr;
4543+
Result = make<PackIndexing>(Pattern, Index);
4544+
break;
4545+
}
45134546
// Exception specifier on a function type.
45144547
case 'o':
45154548
case 'O':
@@ -5354,6 +5387,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
53545387
return nullptr;
53555388
return make<ParameterPackExpansion>(Child);
53565389
}
5390+
if (consumeIf("sy")) {
5391+
Node *Pattern = look() == 'T' ? getDerived().parseTemplateParam()
5392+
: getDerived().parseFunctionParam();
5393+
if (Pattern == nullptr)
5394+
return nullptr;
5395+
Node *Index = getDerived().parseExpr();
5396+
if (Index == nullptr)
5397+
return nullptr;
5398+
return make<PackIndexing>(Pattern, Index);
5399+
}
53575400
if (consumeIf("sZ")) {
53585401
if (look() == 'T') {
53595402
Node *R = getDerived().parseTemplateParam();

libcxxabi/src/demangle/ItaniumNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,5 @@ NODE(ExprRequirement)
100100
NODE(TypeRequirement)
101101
NODE(NestedRequirement)
102102
NODE(ExplicitObjectParameter)
103-
103+
NODE(PackIndexing)
104104
#undef NODE

libcxxabi/test/test_demangle.pass.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30220,6 +30220,11 @@ const char* cases[][2] = {
3022030220
{"_ZZNH3Foo3fooES_iENK4Foo24foo2Ev", "Foo::foo(this Foo, int)::Foo2::foo2() const" },
3022130221
{"_ZNH3FooclERKS_", "Foo::operator()(this Foo const&)"},
3022230222

30223+
30224+
// C++26 pack indexing
30225+
{"_Z3fooILi0ETpTnDaJLi1ELi2EEEDTsyT0_T_Ev", "decltype((1, 2...)[0]) foo<0, 1, 2>()"},
30226+
{"_Z1gILi0EJciEEDyT0_T_v", "(char, int)[0] g<0, char, int>()"},
30227+
3022330228
// fixed-point types as defined in the N1169 draft of ISO/IEC DTR 18037
3022430229
{"_Z1fDAs", "f(short _Accum)"},
3022530230
{"_Z1fDAt", "f(unsigned short _Accum)"},

llvm/include/llvm/Demangle/ItaniumDemangle.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,27 @@ class ParameterPackExpansion final : public Node {
15211521
}
15221522
};
15231523

1524+
class PackIndexing final : public Node {
1525+
const Node *Pattern;
1526+
const Node *Index;
1527+
1528+
public:
1529+
PackIndexing(const Node *Pattern_, const Node *Index_)
1530+
: Node(KPackIndexing), Pattern(Pattern_), Index(Index_) {}
1531+
1532+
template <typename Fn> void match(Fn F) const { F(Pattern, Index); }
1533+
1534+
void printLeft(OutputBuffer &OB) const override {
1535+
OB.printOpen('(');
1536+
ParameterPackExpansion PPE(Pattern);
1537+
PPE.printLeft(OB);
1538+
OB.printClose(')');
1539+
OB.printOpen('[');
1540+
Index->printLeft(OB);
1541+
OB.printClose(']');
1542+
}
1543+
};
1544+
15241545
class TemplateArgs final : public Node {
15251546
NodeArray Params;
15261547
Node *Requires;
@@ -4510,6 +4531,18 @@ Node *AbstractManglingParser<Derived, Alloc>::parseType() {
45104531
Result = make<ParameterPackExpansion>(Child);
45114532
break;
45124533
}
4534+
// ::= Dy <type> <expression> # pack indexing (C++26)
4535+
case 'y': {
4536+
First += 2;
4537+
Node *Pattern = getDerived().parseType();
4538+
if (!Pattern)
4539+
return nullptr;
4540+
Node *Index = getDerived().parseExpr();
4541+
if (!Index)
4542+
return nullptr;
4543+
Result = make<PackIndexing>(Pattern, Index);
4544+
break;
4545+
}
45134546
// Exception specifier on a function type.
45144547
case 'o':
45154548
case 'O':
@@ -5354,6 +5387,16 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExpr() {
53545387
return nullptr;
53555388
return make<ParameterPackExpansion>(Child);
53565389
}
5390+
if (consumeIf("sy")) {
5391+
Node *Pattern = look() == 'T' ? getDerived().parseTemplateParam()
5392+
: getDerived().parseFunctionParam();
5393+
if (Pattern == nullptr)
5394+
return nullptr;
5395+
Node *Index = getDerived().parseExpr();
5396+
if (Index == nullptr)
5397+
return nullptr;
5398+
return make<PackIndexing>(Pattern, Index);
5399+
}
53575400
if (consumeIf("sZ")) {
53585401
if (look() == 'T') {
53595402
Node *R = getDerived().parseTemplateParam();

llvm/include/llvm/Demangle/ItaniumNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,5 +100,5 @@ NODE(ExprRequirement)
100100
NODE(TypeRequirement)
101101
NODE(NestedRequirement)
102102
NODE(ExplicitObjectParameter)
103-
103+
NODE(PackIndexing)
104104
#undef NODE

0 commit comments

Comments
 (0)