<div dir="ltr"><div dir="ltr">On Wed, Sep 4, 2019 at 9:22 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Author: rsmith<br>
Date: Wed Sep 4 18:23:47 2019<br>
New Revision: 371004<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=371004&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=371004&view=rev</a><br>
Log:<br>
[c++20] Fix some ambiguities in our mangling of lambdas with explicit<br>
template parameters.<br>
<br>
This finishes the implementation of the proposal described in<br>
<a href="https://github.com/itanium-cxx-abi/cxx-abi/issues/31" rel="noreferrer" target="_blank">https://github.com/itanium-cxx-abi/cxx-abi/issues/31</a>. (We already<br>
implemented the <lambda-sig> extensions, but didn't take them into<br>
account when computing mangling numbers, and didn't deal properly with<br>
expanded parameter packs, and didn't disambiguate between different<br>
levels of template parameters in manglings.)<br>
<br>
Modified:<br>
cfe/trunk/include/clang/AST/Mangle.h<br>
cfe/trunk/lib/AST/DeclBase.cpp<br>
cfe/trunk/lib/AST/ItaniumCXXABI.cpp<br>
cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
cfe/trunk/lib/Sema/SemaLambda.cpp<br>
cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp<br>
<br>
Modified: cfe/trunk/include/clang/AST/Mangle.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/AST/Mangle.h (original)<br>
+++ cfe/trunk/include/clang/AST/Mangle.h Wed Sep 4 18:23:47 2019<br>
@@ -170,6 +170,8 @@ public:<br>
virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D,<br>
raw_ostream &) = 0;<br>
<br>
+ virtual void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) = 0;<br>
+<br>
static bool classof(const MangleContext *C) {<br>
return C->getKind() == MK_Itanium;<br>
}<br>
<br>
Modified: cfe/trunk/lib/AST/DeclBase.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/DeclBase.cpp (original)<br>
+++ cfe/trunk/lib/AST/DeclBase.cpp Wed Sep 4 18:23:47 2019<br>
@@ -12,6 +12,7 @@<br>
<br>
#include "clang/AST/DeclBase.h"<br>
#include "clang/AST/ASTContext.h"<br>
+#include "clang/AST/ASTLambda.h"<br>
#include "clang/AST/ASTMutationListener.h"<br>
#include "clang/AST/Attr.h"<br>
#include "clang/AST/AttrIterator.h"<br>
@@ -1043,6 +1044,12 @@ DeclContext *DeclContext::getLookupParen<br>
getLexicalParent()->getRedeclContext()->isRecord())<br>
return getLexicalParent();<br>
<br>
+ // A lookup within the call operator of a lambda never looks in the lambda<br>
+ // class; instead, skip to the context in which that closure type is<br>
+ // declared.<br>
+ if (isLambdaCallOperator(this))<br>
+ return getParent()->getParent();<br>
+<br>
return getParent();<br>
}<br>
<br>
<br>
Modified: cfe/trunk/lib/AST/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumCXXABI.cpp?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumCXXABI.cpp?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/AST/ItaniumCXXABI.cpp Wed Sep 4 18:23:47 2019<br>
@@ -19,10 +19,12 @@<br>
#include "CXXABI.h"<br>
#include "clang/AST/ASTContext.h"<br>
#include "clang/AST/DeclCXX.h"<br>
+#include "clang/AST/Mangle.h"<br>
#include "clang/AST/MangleNumberingContext.h"<br>
#include "clang/AST/RecordLayout.h"<br>
#include "clang/AST/Type.h"<br>
#include "clang/Basic/TargetInfo.h"<br>
+#include "llvm/ADT/FoldingSet.h"<br>
#include "llvm/ADT/iterator.h"<br>
<br>
using namespace clang;<br>
@@ -73,10 +75,33 @@ struct DecompositionDeclName {<br>
}<br>
<br>
namespace llvm {<br>
+template<typename T> bool isDenseMapKeyEmpty(T V) {<br>
+ return llvm::DenseMapInfo<T>::isEqual(<br>
+ V, llvm::DenseMapInfo<T>::getEmptyKey());<br>
+}<br>
+template<typename T> bool isDenseMapKeyTombstone(T V) {<br>
+ return llvm::DenseMapInfo<T>::isEqual(<br>
+ V, llvm::DenseMapInfo<T>::getTombstoneKey());<br>
+}<br>
+<br>
+template<typename T><br>
+Optional<bool> areDenseMapKeysEqualSpecialValues(T LHS, T RHS) {<br>
+ bool LHSEmpty = isDenseMapKeyEmpty(LHS);<br>
+ bool RHSEmpty = isDenseMapKeyEmpty(RHS);<br>
+ if (LHSEmpty || RHSEmpty)<br>
+ return LHSEmpty && RHSEmpty;<br>
+<br>
+ bool LHSTombstone = isDenseMapKeyTombstone(LHS);<br>
+ bool RHSTombstone = isDenseMapKeyTombstone(RHS);<br>
+ if (LHSTombstone || RHSTombstone)<br>
+ return LHSTombstone && RHSTombstone;<br>
+<br>
+ return None;<br>
+}<br>
+<br>
template<><br>
struct DenseMapInfo<DecompositionDeclName> {<br>
using ArrayInfo = llvm::DenseMapInfo<ArrayRef<const BindingDecl*>>;<br>
- using IdentInfo = llvm::DenseMapInfo<const IdentifierInfo*>;<br>
static DecompositionDeclName getEmptyKey() {<br>
return {ArrayInfo::getEmptyKey()};<br>
}<br>
@@ -88,10 +113,10 @@ struct DenseMapInfo<DecompositionDeclNam<br>
return llvm::hash_combine_range(Key.begin(), Key.end());<br>
}<br>
static bool isEqual(DecompositionDeclName LHS, DecompositionDeclName RHS) {<br>
- if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getEmptyKey()))<br>
- return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getEmptyKey());<br>
- if (ArrayInfo::isEqual(LHS.Bindings, ArrayInfo::getTombstoneKey()))<br>
- return ArrayInfo::isEqual(RHS.Bindings, ArrayInfo::getTombstoneKey());<br>
+ if (Optional<bool> Result = areDenseMapKeysEqualSpecialValues(<br>
+ LHS.Bindings, RHS.Bindings))<br>
+ return *Result;<br>
+<br>
return LHS.Bindings.size() == RHS.Bindings.size() &&<br>
std::equal(LHS.begin(), LHS.end(), RHS.begin());<br>
}<br>
@@ -103,29 +128,32 @@ namespace {<br>
/// Keeps track of the mangled names of lambda expressions and block<br>
/// literals within a particular context.<br>
class ItaniumNumberingContext : public MangleNumberingContext {<br>
- llvm::DenseMap<const Type *, unsigned> ManglingNumbers;<br>
+ ItaniumMangleContext *Mangler;<br>
+ llvm::StringMap<unsigned> LambdaManglingNumbers;<br>
+ unsigned BlockManglingNumber = 0;<br>
llvm::DenseMap<const IdentifierInfo *, unsigned> VarManglingNumbers;<br>
llvm::DenseMap<const IdentifierInfo *, unsigned> TagManglingNumbers;<br>
llvm::DenseMap<DecompositionDeclName, unsigned><br>
DecompsitionDeclManglingNumbers;<br>
<br>
public:<br>
+ ItaniumNumberingContext(ItaniumMangleContext *Mangler) : Mangler(Mangler) {}<br>
+<br>
unsigned getManglingNumber(const CXXMethodDecl *CallOperator) override {<br>
- const FunctionProtoType *Proto =<br>
- CallOperator->getType()->getAs<FunctionProtoType>();<br>
- ASTContext &Context = CallOperator->getASTContext();<br>
-<br>
- FunctionProtoType::ExtProtoInfo EPI;<br>
- EPI.Variadic = Proto->isVariadic();<br>
- QualType Key =<br>
- Context.getFunctionType(Context.VoidTy, Proto->getParamTypes(), EPI);<br>
- Key = Context.getCanonicalType(Key);<br>
- return ++ManglingNumbers[Key->castAs<FunctionProtoType>()];<br>
+ const CXXRecordDecl *Lambda = CallOperator->getParent();<br>
+ assert(Lambda->isLambda());<br>
+<br>
+ // Computation of the <lambda-sig> is non-trivial and subtle. Rather than<br>
+ // duplicating it here, just mangle the <lambda-sig> directly.<br>
+ llvm::SmallString<128> LambdaSig;<br>
+ llvm::raw_svector_ostream Out(LambdaSig);<br>
+ Mangler->mangleLambdaSig(Lambda, Out);<br>
+<br>
+ return ++LambdaManglingNumbers[LambdaSig];<br>
}<br>
<br>
unsigned getManglingNumber(const BlockDecl *BD) override {<br>
- const Type *Ty = nullptr;<br>
- return ++ManglingNumbers[Ty];<br>
+ return ++BlockManglingNumber;<br>
}<br>
<br>
unsigned getStaticLocalNumber(const VarDecl *VD) override {<br>
@@ -154,10 +182,13 @@ public:<br>
};<br>
<br>
class ItaniumCXXABI : public CXXABI {<br>
+private:<br>
+ std::unique_ptr<MangleContext> Mangler;<br>
protected:<br>
ASTContext &Context;<br>
public:<br>
- ItaniumCXXABI(ASTContext &Ctx) : Context(Ctx) { }<br>
+ ItaniumCXXABI(ASTContext &Ctx)<br>
+ : Mangler(Ctx.createMangleContext()), Context(Ctx) {}<br>
<br>
MemberPointerInfo<br>
getMemberPointerInfo(const MemberPointerType *MPT) const override {<br>
@@ -218,7 +249,8 @@ public:<br>
<br>
std::unique_ptr<MangleNumberingContext><br>
createMangleNumberingContext() const override {<br>
- return std::make_unique<ItaniumNumberingContext>();<br>
+ return std::make_unique<ItaniumNumberingContext>(<br>
+ cast<ItaniumMangleContext>(Mangler.get()));<br>
}<br>
};<br>
}<br>
<br>
Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)<br>
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Sep 4 18:23:47 2019<br>
@@ -170,6 +170,8 @@ public:<br>
<br>
void mangleStringLiteral(const StringLiteral *, raw_ostream &) override;<br>
<br>
+ void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;<br>
+<br>
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {<br>
// Lambda closure types are already numbered.<br>
if (isLambda(ND))<br>
@@ -424,6 +426,7 @@ public:<br>
void mangleName(const NamedDecl *ND);<br>
void mangleType(QualType T);<br>
void mangleNameOrStandardSubstitution(const NamedDecl *ND);<br>
+ void mangleLambdaSig(const CXXRecordDecl *Lambda);<br>
<br>
private:<br>
<br>
@@ -550,7 +553,7 @@ private:<br>
void mangleTemplateArgs(const TemplateArgumentList &AL);<br>
void mangleTemplateArg(TemplateArgument A);<br>
<br>
- void mangleTemplateParameter(unsigned Index);<br>
+ void mangleTemplateParameter(unsigned Depth, unsigned Index);<br>
<br>
void mangleFunctionParam(const ParmVarDecl *parm);<br>
<br>
@@ -965,7 +968,7 @@ void CXXNameMangler::mangleUnscopedTempl<br>
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {<br>
assert(!AdditionalAbiTags &&<br>
"template template param cannot have abi tags");<br>
- mangleTemplateParameter(TTP->getIndex());<br>
+ mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());<br>
} else if (isa<BuiltinTemplateDecl>(ND)) {<br>
mangleUnscopedName(ND, AdditionalAbiTags);<br>
} else {<br>
@@ -1686,16 +1689,42 @@ void CXXNameMangler::mangleUnqualifiedBl<br>
// ::= Tn <type> # template non-type parameter<br>
// ::= Tt <template-param-decl>* E # template template parameter<br></blockquote><div><br></div><div>^ update comment?</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
void CXXNameMangler::mangleTemplateParamDecl(const NamedDecl *Decl) {<br>
- if (isa<TemplateTypeParmDecl>(Decl)) {<br>
+ if (auto *Ty = dyn_cast<TemplateTypeParmDecl>(Decl)) {<br>
+ if (Ty->isParameterPack())<br>
+ Out << "Tp";<br>
Out << "Ty";<br>
} else if (auto *Tn = dyn_cast<NonTypeTemplateParmDecl>(Decl)) {<br>
- Out << "Tn";<br>
- mangleType(Tn->getType());<br>
+ if (Tn->isExpandedParameterPack()) {<br>
+ for (unsigned I = 0, N = Tn->getNumExpansionTypes(); I != N; ++I) {<br>
+ Out << "Tn";<br>
+ mangleType(Tn->getExpansionType(I));<br>
+ }<br>
+ } else {<br>
+ QualType T = Tn->getType();<br>
+ if (Tn->isParameterPack()) {<br>
+ Out << "Tp";<br>
+ T = T->castAs<PackExpansionType>()->getPattern();<br>
+ }<br>
+ Out << "Tn";<br>
+ mangleType(T);<br>
+ }<br>
} else if (auto *Tt = dyn_cast<TemplateTemplateParmDecl>(Decl)) {<br>
- Out << "Tt";<br>
- for (auto *Param : *Tt->getTemplateParameters())<br>
- mangleTemplateParamDecl(Param);<br>
- Out << "E";<br>
+ if (Tt->isExpandedParameterPack()) {<br>
+ for (unsigned I = 0, N = Tt->getNumExpansionTemplateParameters(); I != N;<br>
+ ++I) {<br>
+ Out << "Tt";<br>
+ for (auto *Param : *Tt->getExpansionTemplateParameters(I))<br>
+ mangleTemplateParamDecl(Param);<br>
+ Out << "E";<br>
+ }<br>
+ } else {<br>
+ if (Tt->isParameterPack())<br>
+ Out << "Tp";<br>
+ Out << "Tt";<br>
+ for (auto *Param : *Tt->getTemplateParameters())<br>
+ mangleTemplateParamDecl(Param);<br>
+ Out << "E";<br>
+ }<br>
}<br>
}<br>
<br>
@@ -1726,12 +1755,7 @@ void CXXNameMangler::mangleLambda(const<br>
}<br>
<br>
Out << "Ul";<br>
- for (auto *D : Lambda->getLambdaExplicitTemplateParameters())<br>
- mangleTemplateParamDecl(D);<br>
- const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-><br>
- getAs<FunctionProtoType>();<br>
- mangleBareFunctionType(Proto, /*MangleReturnType=*/false,<br>
- Lambda->getLambdaStaticInvoker());<br>
+ mangleLambdaSig(Lambda);<br>
Out << "E";<br>
<br>
// The number is omitted for the first closure type with a given<br>
@@ -1746,6 +1770,15 @@ void CXXNameMangler::mangleLambda(const<br>
Out << '_';<br>
}<br>
<br>
+void CXXNameMangler::mangleLambdaSig(const CXXRecordDecl *Lambda) {<br>
+ for (auto *D : Lambda->getLambdaExplicitTemplateParameters())<br>
+ mangleTemplateParamDecl(D);<br>
+ const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-><br>
+ getAs<FunctionProtoType>();<br>
+ mangleBareFunctionType(Proto, /*MangleReturnType=*/false,<br>
+ Lambda->getLambdaStaticInvoker());<br>
+}<br>
+<br>
void CXXNameMangler::manglePrefix(NestedNameSpecifier *qualifier) {<br>
switch (qualifier->getKind()) {<br>
case NestedNameSpecifier::Global:<br>
@@ -1852,7 +1885,7 @@ void CXXNameMangler::mangleTemplatePrefi<br>
<br>
// <template-template-param> ::= <template-param><br>
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(ND)) {<br>
- mangleTemplateParameter(TTP->getIndex());<br>
+ mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());<br>
} else {<br>
manglePrefix(getEffectiveDeclContext(ND), NoFunction);<br>
if (isa<BuiltinTemplateDecl>(ND))<br>
@@ -1885,8 +1918,8 @@ void CXXNameMangler::mangleType(Template<br>
goto HaveDecl;<br>
<br>
HaveDecl:<br>
- if (isa<TemplateTemplateParmDecl>(TD))<br>
- mangleTemplateParameter(cast<TemplateTemplateParmDecl>(TD)->getIndex());<br>
+ if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(TD))<br>
+ mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());<br>
else<br>
mangleName(TD);<br>
break;<br>
@@ -2964,7 +2997,7 @@ void CXXNameMangler::mangleType(const Me<br>
<br>
// <type> ::= <template-param><br>
void CXXNameMangler::mangleType(const TemplateTypeParmType *T) {<br>
- mangleTemplateParameter(T->getIndex());<br>
+ mangleTemplateParameter(T->getDepth(), T->getIndex());<br>
}<br>
<br>
// <type> ::= <template-param><br>
@@ -3535,7 +3568,7 @@ void CXXNameMangler::mangleDeclRefExpr(c<br>
<br>
case Decl::NonTypeTemplateParm:<br>
const NonTypeTemplateParmDecl *PD = cast<NonTypeTemplateParmDecl>(D);<br>
- mangleTemplateParameter(PD->getIndex());<br>
+ mangleTemplateParameter(PD->getDepth(), PD->getIndex());<br>
break;<br>
}<br>
}<br>
@@ -4264,13 +4297,13 @@ recurse:<br>
Out << "sZ";<br>
const NamedDecl *Pack = SPE->getPack();<br>
if (const TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Pack))<br>
- mangleTemplateParameter(TTP->getIndex());<br>
+ mangleTemplateParameter(TTP->getDepth(), TTP->getIndex());<br>
else if (const NonTypeTemplateParmDecl *NTTP<br>
= dyn_cast<NonTypeTemplateParmDecl>(Pack))<br>
- mangleTemplateParameter(NTTP->getIndex());<br>
+ mangleTemplateParameter(NTTP->getDepth(), NTTP->getIndex());<br>
else if (const TemplateTemplateParmDecl *TempTP<br>
= dyn_cast<TemplateTemplateParmDecl>(Pack))<br>
- mangleTemplateParameter(TempTP->getIndex());<br>
+ mangleTemplateParameter(TempTP->getDepth(), TempTP->getIndex());<br>
else<br>
mangleFunctionParam(cast<ParmVarDecl>(Pack));<br>
break;<br>
@@ -4557,13 +4590,21 @@ void CXXNameMangler::mangleTemplateArg(T<br>
}<br>
}<br>
<br>
-void CXXNameMangler::mangleTemplateParameter(unsigned Index) {<br>
+void CXXNameMangler::mangleTemplateParameter(unsigned Depth, unsigned Index) {<br>
// <template-param> ::= T_ # first template parameter<br>
// ::= T <parameter-2 non-negative number> _<br>
- if (Index == 0)<br>
- Out << "T_";<br>
- else<br>
- Out << 'T' << (Index - 1) << '_';<br>
+ // ::= TL <L-1 non-negative number> __<br>
+ // ::= TL <L-1 non-negative number> _<br>
+ // <parameter-2 non-negative number> _<br>
+ //<br>
+ // The latter two manglings are from a proposal here:<br>
+ // <a href="https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117" rel="noreferrer" target="_blank">https://github.com/itanium-cxx-abi/cxx-abi/issues/31#issuecomment-528122117</a><br>
+ Out << 'T';<br>
+ if (Depth != 0)<br>
+ Out << 'L' << (Depth - 1) << '_';<br>
+ if (Index != 0)<br>
+ Out << (Index - 1);<br>
+ Out << '_';<br>
}<br>
<br>
void CXXNameMangler::mangleSeqID(unsigned SeqID) {<br>
@@ -5080,6 +5121,12 @@ void ItaniumMangleContextImpl::mangleStr<br>
llvm_unreachable("Can't mangle string literals");<br>
}<br>
<br>
+void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,<br>
+ raw_ostream &Out) {<br>
+ CXXNameMangler Mangler(*this, Out);<br>
+ Mangler.mangleLambdaSig(Lambda);<br>
+}<br>
+<br>
ItaniumMangleContext *<br>
ItaniumMangleContext::create(ASTContext &Context, DiagnosticsEngine &Diags) {<br>
return new ItaniumMangleContextImpl(Context, Diags);<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaLambda.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Sep 4 18:23:47 2019<br>
@@ -407,6 +407,8 @@ CXXMethodDecl *Sema::startLambdaDefiniti<br>
MethodType, MethodTypeInfo, SC_None,<br>
/*isInline=*/true, ConstexprKind, EndLoc);<br>
Method->setAccess(AS_public);<br>
+ if (!TemplateParams)<br>
+ Class->addDecl(Method);<br>
<br>
// Temporarily set the lexical declaration context to the current<br>
// context, so that the Scope stack matches the lexical nesting.<br>
@@ -418,9 +420,10 @@ CXXMethodDecl *Sema::startLambdaDefiniti<br>
TemplateParams,<br>
Method) : nullptr;<br>
if (TemplateMethod) {<br>
- TemplateMethod->setLexicalDeclContext(CurContext);<br>
TemplateMethod->setAccess(AS_public);<br>
Method->setDescribedFunctionTemplate(TemplateMethod);<br>
+ Class->addDecl(TemplateMethod);<br>
+ TemplateMethod->setLexicalDeclContext(CurContext);<br>
}<br>
<br>
// Add parameters.<br>
@@ -1641,8 +1644,9 @@ ExprResult Sema::BuildLambdaExpr(SourceL<br>
? CallOperator->getDescribedFunctionTemplate()<br>
: cast<Decl>(CallOperator);<br>
<br>
+ // FIXME: Is this really the best choice? Keeping the lexical decl context<br>
+ // set as CurContext seems more faithful to the source.<br>
TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);<br>
- Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);<br>
<br>
PopExpressionEvaluationContext();<br>
<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp?rev=371004&r1=371003&r2=371004&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp?rev=371004&r1=371003&r2=371004&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp Wed Sep 4 18:23:47 2019<br>
@@ -33,9 +33,68 @@ void call_inline_func() {<br>
inline_func();<br>
}<br>
<br>
+template<typename T, int> struct X {};<br>
+<br>
+inline auto pack = []<typename ...T, T ...N>(T (&...)[N]) {};<br>
+int arr1[] = {1};<br>
+int arr2[] = {1, 2};<br>
+// CHECK: @_ZNK4packMUlTpTyTpTnT_DpRAT0__S_E_clIJiiEJLi1ELi2EEEEDaS2_(<br>
+void use_pack() { pack(arr1, arr2); }<br>
+<br>
+inline void collision() {<br>
+ auto a = []<typename T, template<typename U, T> typename>{};<br>
+ auto b = []<typename T, template<typename U, U> typename>{};<br>
+ auto c = []<typename T, template<typename U, T> typename>{};<br>
+ a.operator()<int, X>();<br>
+ // CHECK: @_ZZ9collisionvENKUlTyTtTyTnT_EvE_clIi1XEEDav<br>
+ b.operator()<int, X>();<br>
+ // CHECK: @_ZZ9collisionvENKUlTyTtTyTnTL0__EvE_clIi1XEEDav<br>
+ c.operator()<int, X>();<br>
+ // CHECK: @_ZZ9collisionvENKUlTyTtTyTnT_EvE0_clIi1XEEDav<br>
+}<br>
+void use_collision() { collision(); }<br>
+<br>
template<typename> void f() {<br>
// CHECK: define linkonce_odr {{.*}} @_ZZ1fIiEvvENKUlT_E_clIiEEDaS0_(<br>
auto x = [](auto){};<br>
x(0);<br>
}<br>
void use_f() { f<int>(); }<br>
+<br>
+template<typename> struct Y {<br>
+ template<int> struct Z {};<br>
+};<br>
+<br>
+template<typename ...T> void expanded() {<br>
+ auto x = []<T..., template<T> typename...>{};<br>
+ auto y = []<int, template<int> typename>{};<br>
+ auto z = []<int, int, template<int> typename, template<int> typename>{};<br>
+ // FIXME: Should we really require 'template' for y and z?<br>
+ x.template operator()<(T())..., Y<T>::template Z...>();<br>
+ y.template operator()<0, Y<int>::Z>();<br>
+ y.template operator()<1, Y<int>::Z>();<br>
+ z.template operator()<1, 2, Y<int>::Z, Y<float>::Z>();<br>
+}<br>
+void use_expanded() {<br>
+ // CHECK: @_ZZ8expandedIJEEvvENKUlvE_clIJEJEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJEEvvENKUlTniTtTniEvE_clILi0EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJEEvvENKUlTniTtTniEvE_clILi1EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJEEvvENKUlTniTniTtTniETtTniEvE_clILi1ELi2EN1YIiE1ZENS2_IfE1ZEEEDav(<br>
+ expanded<>();<br>
+<br>
+ // FIXME: Should we really be using J...E for arguments corresponding to an<br>
+ // expanded parameter pack?<br>
+ // Note that the <lambda-sig>s of 'x' and 'y' collide here, after pack expansion.<br>
+ // CHECK: @_ZZ8expandedIJiEEvvENKUlTniTtTniEvE_clIJLi0EEJN1YIiE1ZEEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiEEvvENKUlTniTtTniEvE0_clILi0EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiEEvvENKUlTniTtTniEvE0_clILi1EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiEEvvENKUlTniTniTtTniETtTniEvE_clILi1ELi2EN1YIiE1ZENS2_IfE1ZEEEDav(<br>
+ expanded<int>();<br>
+<br>
+ // Note that the <lambda-sig>s of 'x' and 'z' collide here, after pack expansion.<br>
+ // CHECK: @_ZZ8expandedIJiiEEvvENKUlTniTniTtTniETtTniEvE_clIJLi0ELi0EEJN1YIiE1ZES4_EEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiiEEvvENKUlTniTtTniEvE_clILi0EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiiEEvvENKUlTniTtTniEvE_clILi1EN1YIiE1ZEEEDav(<br>
+ // CHECK: @_ZZ8expandedIJiiEEvvENKUlTniTniTtTniETtTniEvE0_clILi1ELi2EN1YIiE1ZENS2_IfE1ZEEEDav(<br>
+ expanded<int, int>();<br>
+}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>