<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>