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