[clang] [Sema] 81145 (PR #81150)
Younan Zhang via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 11 06:59:47 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 1/3] 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 <zyn7109 at gmail.com>
Date: Sat, 10 Feb 2024 15:35:43 +0800
Subject: [PATCH 2/3] 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);
}
>From 23d26a7fd09911845d46e145cd757f92278f218f Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sun, 11 Feb 2024 22:59:31 +0800
Subject: [PATCH 3/3] {read,writ}er
---
clang/lib/Serialization/ASTReaderDecl.cpp | 20 ++++++++++++++------
clang/lib/Serialization/ASTWriterDecl.cpp | 1 +
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index ffba04f28782ea..f87d8113813442 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -161,10 +161,12 @@ namespace clang {
void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update,
Decl *LambdaContext = nullptr,
- unsigned IndexInLambdaContext = 0);
+ unsigned IndexInLambdaContext = 0,
+ Decl *LambdaInstantiatingContext = nullptr);
void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
const CXXRecordDecl *D, Decl *LambdaContext,
- unsigned IndexInLambdaContext);
+ unsigned IndexInLambdaContext,
+ Decl *LambdaInstantiatingContext);
void MergeDefinitionData(CXXRecordDecl *D,
struct CXXRecordDecl::DefinitionData &&NewDD);
void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
@@ -1969,7 +1971,8 @@ void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl(
void ASTDeclReader::ReadCXXDefinitionData(
struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D,
- Decl *LambdaContext, unsigned IndexInLambdaContext) {
+ Decl *LambdaContext, unsigned IndexInLambdaContext,
+ Decl *LambdaInstantiatingContext) {
BitsUnpacker CXXRecordDeclBits = Record.readInt();
@@ -2031,6 +2034,7 @@ void ASTDeclReader::ReadCXXDefinitionData(
Reader.getContext().DeviceLambdaManglingNumbers[D] = DeviceManglingNumber;
Lambda.IndexInContext = IndexInLambdaContext;
Lambda.ContextDecl = LambdaContext;
+ Lambda.InstantiatingContextDecl = LambdaInstantiatingContext;
Capture *ToCapture = nullptr;
if (Lambda.NumCaptures) {
ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) *
@@ -2162,7 +2166,8 @@ void ASTDeclReader::MergeDefinitionData(
void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update,
Decl *LambdaContext,
- unsigned IndexInLambdaContext) {
+ unsigned IndexInLambdaContext,
+ Decl *LambdaInstantiatingContext) {
struct CXXRecordDecl::DefinitionData *DD;
ASTContext &C = Reader.getContext();
@@ -2184,7 +2189,8 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update,
if (!Canon->DefinitionData)
Canon->DefinitionData = DD;
D->DefinitionData = Canon->DefinitionData;
- ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext);
+ ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext,
+ LambdaInstantiatingContext);
// We might already have a different definition for this record. This can
// happen either because we're reading an update record, or because we've
@@ -2219,6 +2225,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
Decl *LambdaContext = nullptr;
unsigned IndexInLambdaContext = 0;
+ Decl *LambdaInstantiatingContext = nullptr;
switch ((CXXRecKind)Record.readInt()) {
case CXXRecNotTemplate:
@@ -2255,6 +2262,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
LambdaContext = readDecl();
if (LambdaContext)
IndexInLambdaContext = Record.readInt();
+ LambdaInstantiatingContext = readDecl();
mergeLambda(D, Redecl, LambdaContext, IndexInLambdaContext);
break;
}
@@ -2263,7 +2271,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
bool WasDefinition = Record.readInt();
if (WasDefinition)
ReadCXXRecordDefinition(D, /*Update=*/false, LambdaContext,
- IndexInLambdaContext);
+ IndexInLambdaContext, LambdaInstantiatingContext);
else
// Propagate DefinitionData pointer from the canonical declaration.
D->DefinitionData = D->getCanonicalDecl()->DefinitionData;
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index f224075643e998..2f9e033040d5f9 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1479,6 +1479,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
} else {
Record.push_back(0);
}
+ Record.AddDeclRef(D->getLambdaInstantiatingContextDecl());
} else {
Record.push_back(CXXRecNotTemplate);
}
More information about the cfe-commits
mailing list