https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/81150
>From d9fe7f3777a27057181eaa008577fc13a30d30ee Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Sat, 10 Feb 2024 15:34:36 +0800 Subject: [PATCH 1/2] fixup --- clang/include/clang/AST/DeclCXX.h | 6 ++++ clang/lib/AST/DeclCXX.cpp | 12 +++++++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 24 ++++++++++++- clang/lib/Sema/TreeTransform.h | 3 ++ clang/test/SemaTemplate/concepts-lambda.cpp | 39 +++++++++++++++++++++ 5 files changed, 83 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index 9cebaff63bb0db..a2c56b3c4cf2ac 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -426,6 +426,8 @@ class CXXRecordDecl : public RecordDecl { /// or within a data member initializer. LazyDeclPtr ContextDecl; + LazyDeclPtr InstantiatingContextDecl; + /// The lists of captures, both explicit and implicit, for this /// lambda. One list is provided for each merged copy of the lambda. /// The first list corresponds to the canonical definition. @@ -1786,6 +1788,10 @@ class CXXRecordDecl : public RecordDecl { /// the declaration context suffices. Decl *getLambdaContextDecl() const; + void setLambdaInstantiatingContextDecl(Decl *D); + + Decl *getLambdaInstantiatingContextDecl() const; + /// Retrieve the index of this lambda within the context declaration returned /// by getLambdaContextDecl(). unsigned getLambdaIndexInContext() const { diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index 117e802dae2d9d..9260be78aeefaa 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1685,6 +1685,16 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const { return getLambdaData().ContextDecl.get(Source); } +Decl *CXXRecordDecl::getLambdaInstantiatingContextDecl() const { + assert(isLambda() && "Not a lambda closure type!"); + ExternalASTSource *Source = getParentASTContext().getExternalSource(); + return getLambdaData().InstantiatingContextDecl.get(Source); +} + +void CXXRecordDecl::setLambdaInstantiatingContextDecl(Decl *D) { + getLambdaData().InstantiatingContextDecl = D; +} + void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { assert(isLambda() && "Not a lambda closure type!"); getLambdaData().ManglingNumber = Numbering.ManglingNumber; @@ -1693,6 +1703,8 @@ void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) { Numbering.DeviceManglingNumber; getLambdaData().IndexInContext = Numbering.IndexInContext; getLambdaData().ContextDecl = Numbering.ContextDecl; + if (Numbering.ContextDecl) + getLambdaData().InstantiatingContextDecl = Numbering.ContextDecl; getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage; } diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 6d59180bc446d2..541bb4081d8f36 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -314,7 +314,7 @@ Response HandleRecordDecl(const CXXRecordDecl *Rec, // This is to make sure we pick up the VarTemplateSpecializationDecl that this // lambda is defined inside of. if (Rec->isLambda()) - if (const Decl *LCD = Rec->getLambdaContextDecl()) + if (const Decl *LCD = Rec->getLambdaInstantiatingContextDecl()) return Response::ChangeDecl(LCD); return Response::UseNextDecl(Rec); @@ -330,6 +330,14 @@ Response HandleImplicitConceptSpecializationDecl( return Response::UseNextDecl(CSD); } +Response HandleTypeAliasTemplateDecl(const TypeAliasTemplateDecl *TATD, + bool ForConstraintInstantiation, + MultiLevelTemplateArgumentList &Result) { + if (ForConstraintInstantiation) + Result.addOuterTemplateArguments(std::nullopt); + return Response::UseNextDecl(TATD); +} + Response HandleGenericDeclContext(const Decl *CurDecl) { return Response::UseNextDecl(CurDecl); } @@ -425,6 +433,10 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs( if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) { R = HandleDefaultTempArgIntoTempTempParam(TTP, Result); } + if (const auto *TAD = dyn_cast<TypeAliasTemplateDecl>(CurDecl)) { + R = HandleTypeAliasTemplateDecl(TAD, ForConstraintInstantiation, + Result); + } } else { R = HandleGenericDeclContext(CurDecl); } @@ -1231,6 +1243,8 @@ namespace { // Whether to evaluate the C++20 constraints or simply substitute into them. bool EvaluateConstraints = true; + llvm::DenseMap<Decl *, Decl *> InstantiatedLambdas; + public: typedef TreeTransform<TemplateInstantiator> inherited; @@ -1353,6 +1367,7 @@ namespace { auto *NewMD = dyn_cast<CXXMethodDecl>(New); if (NewMD && isLambdaCallOperator(NewMD)) { auto *OldMD = dyn_cast<CXXMethodDecl>(Old); + InstantiatedLambdas[OldMD] = NewMD; if (auto *NewTD = NewMD->getDescribedFunctionTemplate()) NewTD->setInstantiatedFromMemberTemplate( OldMD->getDescribedFunctionTemplate()); @@ -1663,6 +1678,13 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { // template parameter. } + if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D)) + if (auto *Method = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl()); + Method && isLambdaCallOperator(Method)) + if (auto Iter = InstantiatedLambdas.find(Method); + Iter != InstantiatedLambdas.end()) + return Iter->second; + return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs); } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 3ed17c3360a83c..95bf67fa4bef0e 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13837,6 +13837,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } getSema().handleLambdaNumbering(Class, NewCallOperator, Numbering); + if (!Class->getLambdaInstantiatingContextDecl() && getSema().inTemplateInstantiation()) + Class->setLambdaInstantiatingContextDecl( + getSema().CodeSynthesisContexts.back().Entity); } // FIXME: Sema's lambda-building mechanism expects us to push an expression diff --git a/clang/test/SemaTemplate/concepts-lambda.cpp b/clang/test/SemaTemplate/concepts-lambda.cpp index 0b7580f91043c7..1694f46fea8fdf 100644 --- a/clang/test/SemaTemplate/concepts-lambda.cpp +++ b/clang/test/SemaTemplate/concepts-lambda.cpp @@ -150,6 +150,45 @@ void foo() { } } // namespace ReturnTypeRequirementInLambda +namespace GH70601 { + +template <class> +concept C = true; + +template <class T, class U> +concept D = C<T> && C<U>; + +template <class T> +auto declval() -> decltype(T()); + +template <class T> +struct S { + template <class U> + using Type = decltype([]<C V>(V) { + return []<D<V> W> { + return W(); + }.template operator()<V>(); + }(U())); + + template <C U> + using ValueType = decltype([]<D<U> V> { + return V(); + }.template operator()<U>()); + + // template <C U> + // using LambdaType = decltype([]<D<U> V> { + // return V(); + // }); + + // using IndirectValueType = decltype(declval<LambdaType<T>>().template operator()<T>()); +}; + +static_assert(__is_same(S<int>::Type<int>, int)); +static_assert(__is_same(S<int>::ValueType<float>, float)); +// static_assert(__is_same(S<char>::IndirectValueType, char)); + +} + namespace GH73418 { void foo() { int x; >From 45e25a81809cfd4e0bcce27d85d004a893aeb5ad Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Sat, 10 Feb 2024 15:35:43 +0800 Subject: [PATCH 2/2] format --- clang/lib/Sema/TreeTransform.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 95bf67fa4bef0e..0a1dad4df8cd94 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13837,7 +13837,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { } getSema().handleLambdaNumbering(Class, NewCallOperator, Numbering); - if (!Class->getLambdaInstantiatingContextDecl() && getSema().inTemplateInstantiation()) + if (!Class->getLambdaInstantiatingContextDecl() && + getSema().inTemplateInstantiation()) Class->setLambdaInstantiatingContextDecl( getSema().CodeSynthesisContexts.back().Entity); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits