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