Skip to content

Commit 7ac4237

Browse files
committed
[c++20] Fix some ambiguities in our mangling of lambdas with explicit
template parameters. This finishes the implementation of the proposal described in itanium-cxx-abi/cxx-abi#31. (We already implemented the <lambda-sig> extensions, but didn't take them into account when computing mangling numbers, and didn't deal properly with expanded parameter packs, and didn't disambiguate between different levels of template parameters in manglings.) llvm-svn: 371004
1 parent 33b8a55 commit 7ac4237

File tree

6 files changed

+200
-49
lines changed

6 files changed

+200
-49
lines changed

clang/include/clang/AST/Mangle.h

+2
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class ItaniumMangleContext : public MangleContext {
170170
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,
171171
raw_ostream &) = 0;
172172

173+
virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;
174+
173175
static bool classof(const MangleContext *C) {
174176
return C->getKind() == MK_Itanium;
175177
}

clang/lib/AST/DeclBase.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
#include "clang/AST/DeclBase.h"
1414
#include "clang/AST/ASTContext.h"
15+
#include "clang/AST/ASTLambda.h"
1516
#include "clang/AST/ASTMutationListener.h"
1617
#include "clang/AST/Attr.h"
1718
#include "clang/AST/AttrIterator.h"
@@ -1043,6 +1044,12 @@ DeclContext *DeclContext::getLookupParent() {
10431044
getLexicalParent()->getRedeclContext()->isRecord())
10441045
return getLexicalParent();
10451046

1047+
// A lookup within the call operator of a lambda never looks in the lambda
1048+
// class; instead, skip to the context in which that closure type is
1049+
// declared.
1050+
if (isLambdaCallOperator(this))
1051+
return getParent()->getParent();
1052+
10461053
return getParent();
10471054
}
10481055

clang/lib/AST/ItaniumCXXABI.cpp

+51-19
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
#include "CXXABI.h"
2020
#include "clang/AST/ASTContext.h"
2121
#include "clang/AST/DeclCXX.h"
22+
#include "clang/AST/Mangle.h"
2223
#include "clang/AST/MangleNumberingContext.h"
2324
#include "clang/AST/RecordLayout.h"
2425
#include "clang/AST/Type.h"
2526
#include "clang/Basic/TargetInfo.h"
27+
#include "llvm/ADT/FoldingSet.h"
2628
#include "llvm/ADT/iterator.h"
2729

2830
using namespace clang;
@@ -73,10 +75,33 @@ struct DecompositionDeclName {
7375
}
7476

7577
namespace llvm {
78+
template<typename T> bool isDenseMapKeyEmpty(T V) {
79+
return llvm::DenseMapInfo<T>::isEqual(
80+
V, llvm::DenseMapInfo<T>::getEmptyKey());
81+
}
82+
template<typename T> bool isDenseMapKeyTombstone(T V) {
83+
return llvm::DenseMapInfo<T>::isEqual(
84+
V, llvm::DenseMapInfo<T>::getTombstoneKey());
85+
}
86+
87+
template<typename T>
88+
Optional<bool> areDenseMapKeysEqualSpecialValues(T LHS, T RHS) {
89+
bool LHSEmpty = isDenseMapKeyEmpty(LHS);
90+
bool RHSEmpty = isDenseMapKeyEmpty(RHS);
91+
if (LHSEmpty || RHSEmpty)
92+
return LHSEmpty && RHSEmpty;
93+
94+
bool LHSTombstone = isDenseMapKeyTombstone(LHS);
95+
bool RHSTombstone = isDenseMapKeyTombstone(RHS);
96+
if (LHSTombstone || RHSTombstone)
97+
return LHSTombstone && RHSTombstone;
98+
99+
return None;
100+
}
101+
76102
template<>
77103
struct DenseMapInfo<DecompositionDeclName> {
78104
using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>;
79-
using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>;
80105
static DecompositionDeclName getEmptyKey() {
81106
return {ArrayInfo::getEmptyKey()};
82107
}
@@ -88,10 +113,10 @@ struct DenseMapInfo<DecompositionDeclName> {
88113
return llvm::hash_combine_range(Key.begin(), Key.end());
89114
}
90115
static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {
91-
if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey()))
92-
return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey());
93-
if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey()))
94-
return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey());
116+
if (Optional<bool> Result = areDenseMapKeysEqualSpecialValues(
117+
LHS.Bindings, RHS.Bindings))
118+
return *Result;
119+
95120
return LHS.Bindings.size() == RHS.Bindings.size() &&
96121
std::equal(LHS.begin(), LHS.end(), RHS.begin());
97122
}
@@ -103,29 +128,32 @@ namespace {
103128
/// Keeps track of the mangled names of lambda expressions and block
104129
/// literals within a particular context.
105130
class ItaniumNumberingContext : public MangleNumberingContext {
106-
llvm::DenseMap<const Type *, unsigned> ManglingNumbers;
131+
ItaniumMangleContext *Mangler;
132+
llvm::StringMap<unsigned> LambdaManglingNumbers;
133+
unsigned BlockManglingNumber = 0;
107134
llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;
108135
llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;
109136
llvm::DenseMap<DecompositionDeclName, unsigned>
110137
DecompsitionDeclManglingNumbers;
111138

112139
public:
140+
ItaniumNumberingContext(ItaniumMangleContext *Mangler) : Mangler(Mangler) {}
141+
113142
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {
114-
const FunctionProtoType *Proto =
115-
CallOperator->getType()->getAs<FunctionProtoType>();
116-
ASTContext &Context = CallOperator->getASTContext();
143+
const CXXRecordDecl *Lambda = CallOperator->getParent();
144+
assert(Lambda->isLambda());
145+
146+
// Computation of the <lambda-sig> is non-trivial and subtle. Rather than
147+
// duplicating it here, just mangle the <lambda-sig> directly.
148+
llvm::SmallString<128> LambdaSig;
149+
llvm::raw_svector_ostream Out(LambdaSig);
150+
Mangler->mangleLambdaSig(Lambda, Out);
117151

118-
FunctionProtoType::ExtProtoInfo EPI;
119-
EPI.Variadic = Proto->isVariadic();
120-
QualType Key =
121-
Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);
122-
Key = Context.getCanonicalType(Key);
123-
return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];
152+
return ++LambdaManglingNumbers[LambdaSig];
124153
}
125154

126155
unsigned getManglingNumber(const BlockDecl *BD) override {
127-
const Type *Ty = nullptr;
128-
return ++ManglingNumbers[Ty];
156+
return ++BlockManglingNumber;
129157
}
130158

131159
unsigned getStaticLocalNumber(const VarDecl *VD) override {
@@ -154,10 +182,13 @@ class ItaniumNumberingContext : public MangleNumberingContext {
154182
};
155183

156184
class ItaniumCXXABI : public CXXABI {
185+
private:
186+
std::unique_ptr<MangleContext> Mangler;
157187
protected:
158188
ASTContext &Context;
159189
public:
160-
ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }
190+
ItaniumCXXABI(ASTContext &Ctx)
191+
: Mangler(Ctx.createMangleContext()), Context(Ctx) {}
161192

162193
MemberPointerInfo
163194
getMemberPointerInfo(const MemberPointerType *MPT) const override {
@@ -218,7 +249,8 @@ class ItaniumCXXABI : public CXXABI {
218249

219250
std::unique_ptr<MangleNumberingContext>
220251
createMangleNumberingContext() const override {
221-
return std::make_unique<ItaniumNumberingContext>();
252+
return std::make_unique<ItaniumNumberingContext>(
253+
cast<ItaniumMangleContext>(Mangler.get()));
222254
}
223255
};
224256
}

clang/lib/AST/ItaniumMangle.cpp

+75-28
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ class ItaniumMangleContextImpl : public ItaniumMangleContext {
170170

171171
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;
172172

173+
void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;
174+
173175
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
174176
// Lambda closure types are already numbered.
175177
if (isLambda(ND))
@@ -424,6 +426,7 @@ class CXXNameMangler {
424426
void mangleName(const NamedDecl *ND);
425427
void mangleType(QualType T);
426428
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
429+
void mangleLambdaSig(const CXXRecordDecl *Lambda);
427430

428431
private:
429432

@@ -550,7 +553,7 @@ class CXXNameMangler {
550553
void mangleTemplateArgs(const TemplateArgumentList &AL);
551554
void mangleTemplateArg(TemplateArgument A);
552555

553-
void mangleTemplateParameter(unsigned Index);
556+
void mangleTemplateParameter(unsigned Depth, unsigned Index);
554557

555558
void mangleFunctionParam(const ParmVarDecl *parm);
556559

@@ -965,7 +968,7 @@ void CXXNameMangler::mangleUnscopedTemplateName(
965968
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
966969
assert(!AdditionalAbiTags &&
967970
"template template param cannot have abi tags");
968-
mangleTemplateParameter(TTP->getIndex());
971+
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
969972
} else if (isa<BuiltinTemplateDecl>(ND)) {
970973
mangleUnscopedName(ND, AdditionalAbiTags);
971974
} else {
@@ -1686,16 +1689,42 @@ void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
16861689
// ::= Tn <type> # template non-type parameter
16871690
// ::= Tt <template-param-decl>* E # template template parameter
16881691
void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {
1689-
if (isa<TemplateTypeParmDecl>(Decl)) {
1692+
if (auto *Ty = dyn_cast<TemplateTypeParmDecl>(Decl)) {
1693+
if (Ty->isParameterPack())
1694+
Out << "Tp";
16901695
Out << "Ty";
16911696
} else if (auto *Tn = dyn_cast<NonTypeTemplateParmDecl>(Decl)) {
1692-
Out << "Tn";
1693-
mangleType(Tn->getType());
1697+
if (Tn->isExpandedParameterPack()) {
1698+
for (unsigned I = 0, N = Tn->getNumExpansionTypes(); I != N; ++I) {
1699+
Out << "Tn";
1700+
mangleType(Tn->getExpansionType(I));
1701+
}
1702+
} else {
1703+
QualType T = Tn->getType();
1704+
if (Tn->isParameterPack()) {
1705+
Out << "Tp";
1706+
T = T->castAs<PackExpansionType>()->getPattern();
1707+
}
1708+
Out << "Tn";
1709+
mangleType(T);
1710+
}
16941711
} else if (auto *Tt = dyn_cast<TemplateTemplateParmDecl>(Decl)) {
1695-
Out << "Tt";
1696-
for (auto *Param : *Tt->getTemplateParameters())
1697-
mangleTemplateParamDecl(Param);
1698-
Out << "E";
1712+
if (Tt->isExpandedParameterPack()) {
1713+
for (unsigned I = 0, N = Tt->getNumExpansionTemplateParameters(); I != N;
1714+
++I) {
1715+
Out << "Tt";
1716+
for (auto *Param : *Tt->getExpansionTemplateParameters(I))
1717+
mangleTemplateParamDecl(Param);
1718+
Out << "E";
1719+
}
1720+
} else {
1721+
if (Tt->isParameterPack())
1722+
Out << "Tp";
1723+
Out << "Tt";
1724+
for (auto *Param : *Tt->getTemplateParameters())
1725+
mangleTemplateParamDecl(Param);
1726+
Out << "E";
1727+
}
16991728
}
17001729
}
17011730

@@ -1726,12 +1755,7 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
17261755
}
17271756

17281757
Out << "Ul";
1729-
for (auto *D : Lambda->getLambdaExplicitTemplateParameters())
1730-
mangleTemplateParamDecl(D);
1731-
const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
1732-
getAs<FunctionProtoType>();
1733-
mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
1734-
Lambda->getLambdaStaticInvoker());
1758+
mangleLambdaSig(Lambda);
17351759
Out << "E";
17361760

17371761
// The number is omitted for the first closure type with a given
@@ -1746,6 +1770,15 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
17461770
Out << '_';
17471771
}
17481772

1773+
void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {
1774+
for (auto *D : Lambda->getLambdaExplicitTemplateParameters())
1775+
mangleTemplateParamDecl(D);
1776+
const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()->
1777+
getAs<FunctionProtoType>();
1778+
mangleBareFunctionType(Proto, /*MangleReturnType=*/false,
1779+
Lambda->getLambdaStaticInvoker());
1780+
}
1781+
17491782
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {
17501783
switch (qualifier->getKind()) {
17511784
case NestedNameSpecifier::Global:
@@ -1852,7 +1885,7 @@ void CXXNameMangler::mangleTemplatePrefix(const TemplateDecl *ND,
18521885

18531886
// <template-template-param> ::= <template-param>
18541887
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {
1855-
mangleTemplateParameter(TTP->getIndex());
1888+
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
18561889
} else {
18571890
manglePrefix(getEffectiveDeclContext(ND), NoFunction);
18581891
if (isa<BuiltinTemplateDecl>(ND))
@@ -1885,8 +1918,8 @@ void CXXNameMangler::mangleType(TemplateName TN) {
18851918
goto HaveDecl;
18861919

18871920
HaveDecl:
1888-
if (isa<TemplateTemplateParmDecl>(TD))
1889-
mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());
1921+
if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD))
1922+
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
18901923
else
18911924
mangleName(TD);
18921925
break;
@@ -2964,7 +2997,7 @@ void CXXNameMangler::mangleType(const MemberPointerType *T) {
29642997

29652998
// <type> ::= <template-param>
29662999
void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {
2967-
mangleTemplateParameter(T->getIndex());
3000+
mangleTemplateParameter(T->getDepth(), T->getIndex());
29683001
}
29693002

29703003
// <type> ::= <template-param>
@@ -3535,7 +3568,7 @@ void CXXNameMangler::mangleDeclRefExpr(const NamedDecl *D) {
35353568

35363569
case Decl::NonTypeTemplateParm:
35373570
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);
3538-
mangleTemplateParameter(PD->getIndex());
3571+
mangleTemplateParameter(PD->getDepth(), PD->getIndex());
35393572
break;
35403573
}
35413574
}
@@ -4264,13 +4297,13 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
42644297
Out << "sZ";
42654298
const NamedDecl *Pack = SPE->getPack();
42664299
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))
4267-
mangleTemplateParameter(TTP->getIndex());
4300+
mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());
42684301
else if (const NonTypeTemplateParmDecl *NTTP
42694302
= dyn_cast<NonTypeTemplateParmDecl>(Pack))
4270-
mangleTemplateParameter(NTTP->getIndex());
4303+
mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex());
42714304
else if (const TemplateTemplateParmDecl *TempTP
42724305
= dyn_cast<TemplateTemplateParmDecl>(Pack))
4273-
mangleTemplateParameter(TempTP->getIndex());
4306+
mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex());
42744307
else
42754308
mangleFunctionParam(cast<ParmVarDecl>(Pack));
42764309
break;
@@ -4557,13 +4590,21 @@ void CXXNameMangler::mangleTemplateArg(TemplateArgument A) {
45574590
}
45584591
}
45594592

4560-
void CXXNameMangler::mangleTemplateParameter(unsigned Index) {
4593+
void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) {
45614594
// <template-param> ::= T_ # first template parameter
45624595
// ::= T <parameter-2 non-negative number> _
4563-
if (Index == 0)
4564-
Out << "T_";
4565-
else
4566-
Out << 'T' << (Index - 1) << '_';
4596+
// ::= TL <L-1 non-negative number> __
4597+
// ::= TL <L-1 non-negative number> _
4598+
// <parameter-2 non-negative number> _
4599+
//
4600+
// The latter two manglings are from a proposal here:
4601+
// https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117
4602+
Out << 'T';
4603+
if (Depth != 0)
4604+
Out << 'L' << (Depth - 1) << '_';
4605+
if (Index != 0)
4606+
Out << (Index - 1);
4607+
Out << '_';
45674608
}
45684609

45694610
void CXXNameMangler::mangleSeqID(unsigned SeqID) {
@@ -5080,6 +5121,12 @@ void ItaniumMangleContextImpl::mangleStringLiteral(const StringLiteral *, raw_os
50805121
llvm_unreachable("Can't mangle string literals");
50815122
}
50825123

5124+
void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,
5125+
raw_ostream &Out) {
5126+
CXXNameMangler Mangler(*this, Out);
5127+
Mangler.mangleLambdaSig(Lambda);
5128+
}
5129+
50835130
ItaniumMangleContext *
50845131
ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {
50855132
return new ItaniumMangleContextImpl(Context, Diags);

0 commit comments

Comments
 (0)