[clang] [Sema] 81145 (PR #81150)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 9 23:35:02 PST 2024
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 <zyn7109 at gmail.com>
Date: Sat, 10 Feb 2024 15:34:36 +0800
Subject: [PATCH] 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;
More information about the cfe-commits
mailing list