Skip to content

Commit d9fe7f3

Browse files
committed
fixup
1 parent c8ca98a commit d9fe7f3

File tree

5 files changed

+83
-1
lines changed

5 files changed

+83
-1
lines changed

clang/include/clang/AST/DeclCXX.h

+6
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,8 @@ class CXXRecordDecl : public RecordDecl {
426426
/// or within a data member initializer.
427427
LazyDeclPtr ContextDecl;
428428

429+
LazyDeclPtr InstantiatingContextDecl;
430+
429431
/// The lists of captures, both explicit and implicit, for this
430432
/// lambda. One list is provided for each merged copy of the lambda.
431433
/// The first list corresponds to the canonical definition.
@@ -1786,6 +1788,10 @@ class CXXRecordDecl : public RecordDecl {
17861788
/// the declaration context suffices.
17871789
Decl *getLambdaContextDecl() const;
17881790

1791+
void setLambdaInstantiatingContextDecl(Decl *D);
1792+
1793+
Decl *getLambdaInstantiatingContextDecl() const;
1794+
17891795
/// Retrieve the index of this lambda within the context declaration returned
17901796
/// by getLambdaContextDecl().
17911797
unsigned getLambdaIndexInContext() const {

clang/lib/AST/DeclCXX.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,16 @@ Decl *CXXRecordDecl::getLambdaContextDecl() const {
16851685
return getLambdaData().ContextDecl.get(Source);
16861686
}
16871687

1688+
Decl *CXXRecordDecl::getLambdaInstantiatingContextDecl() const {
1689+
assert(isLambda() && "Not a lambda closure type!");
1690+
ExternalASTSource *Source = getParentASTContext().getExternalSource();
1691+
return getLambdaData().InstantiatingContextDecl.get(Source);
1692+
}
1693+
1694+
void CXXRecordDecl::setLambdaInstantiatingContextDecl(Decl *D) {
1695+
getLambdaData().InstantiatingContextDecl = D;
1696+
}
1697+
16881698
void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) {
16891699
assert(isLambda() && "Not a lambda closure type!");
16901700
getLambdaData().ManglingNumber = Numbering.ManglingNumber;
@@ -1693,6 +1703,8 @@ void CXXRecordDecl::setLambdaNumbering(LambdaNumbering Numbering) {
16931703
Numbering.DeviceManglingNumber;
16941704
getLambdaData().IndexInContext = Numbering.IndexInContext;
16951705
getLambdaData().ContextDecl = Numbering.ContextDecl;
1706+
if (Numbering.ContextDecl)
1707+
getLambdaData().InstantiatingContextDecl = Numbering.ContextDecl;
16961708
getLambdaData().HasKnownInternalLinkage = Numbering.HasKnownInternalLinkage;
16971709
}
16981710

clang/lib/Sema/SemaTemplateInstantiate.cpp

+23-1
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,7 @@ Response HandleRecordDecl(const CXXRecordDecl *Rec,
314314
// This is to make sure we pick up the VarTemplateSpecializationDecl that this
315315
// lambda is defined inside of.
316316
if (Rec->isLambda())
317-
if (const Decl *LCD = Rec->getLambdaContextDecl())
317+
if (const Decl *LCD = Rec->getLambdaInstantiatingContextDecl())
318318
return Response::ChangeDecl(LCD);
319319

320320
return Response::UseNextDecl(Rec);
@@ -330,6 +330,14 @@ Response HandleImplicitConceptSpecializationDecl(
330330
return Response::UseNextDecl(CSD);
331331
}
332332

333+
Response HandleTypeAliasTemplateDecl(const TypeAliasTemplateDecl *TATD,
334+
bool ForConstraintInstantiation,
335+
MultiLevelTemplateArgumentList &Result) {
336+
if (ForConstraintInstantiation)
337+
Result.addOuterTemplateArguments(std::nullopt);
338+
return Response::UseNextDecl(TATD);
339+
}
340+
333341
Response HandleGenericDeclContext(const Decl *CurDecl) {
334342
return Response::UseNextDecl(CurDecl);
335343
}
@@ -425,6 +433,10 @@ MultiLevelTemplateArgumentList Sema::getTemplateInstantiationArgs(
425433
if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(CurDecl)) {
426434
R = HandleDefaultTempArgIntoTempTempParam(TTP, Result);
427435
}
436+
if (const auto *TAD = dyn_cast<TypeAliasTemplateDecl>(CurDecl)) {
437+
R = HandleTypeAliasTemplateDecl(TAD, ForConstraintInstantiation,
438+
Result);
439+
}
428440
} else {
429441
R = HandleGenericDeclContext(CurDecl);
430442
}
@@ -1231,6 +1243,8 @@ namespace {
12311243
// Whether to evaluate the C++20 constraints or simply substitute into them.
12321244
bool EvaluateConstraints = true;
12331245

1246+
llvm::DenseMap<Decl *, Decl *> InstantiatedLambdas;
1247+
12341248
public:
12351249
typedef TreeTransform<TemplateInstantiator> inherited;
12361250

@@ -1353,6 +1367,7 @@ namespace {
13531367
auto *NewMD = dyn_cast<CXXMethodDecl>(New);
13541368
if (NewMD && isLambdaCallOperator(NewMD)) {
13551369
auto *OldMD = dyn_cast<CXXMethodDecl>(Old);
1370+
InstantiatedLambdas[OldMD] = NewMD;
13561371
if (auto *NewTD = NewMD->getDescribedFunctionTemplate())
13571372
NewTD->setInstantiatedFromMemberTemplate(
13581373
OldMD->getDescribedFunctionTemplate());
@@ -1663,6 +1678,13 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) {
16631678
// template parameter.
16641679
}
16651680

1681+
if (auto *FTD = dyn_cast<FunctionTemplateDecl>(D))
1682+
if (auto *Method = dyn_cast<CXXMethodDecl>(FTD->getTemplatedDecl());
1683+
Method && isLambdaCallOperator(Method))
1684+
if (auto Iter = InstantiatedLambdas.find(Method);
1685+
Iter != InstantiatedLambdas.end())
1686+
return Iter->second;
1687+
16661688
return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
16671689
}
16681690

clang/lib/Sema/TreeTransform.h

+3
Original file line numberDiff line numberDiff line change
@@ -13837,6 +13837,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1383713837
}
1383813838

1383913839
getSema().handleLambdaNumbering(Class, NewCallOperator, Numbering);
13840+
if (!Class->getLambdaInstantiatingContextDecl() && getSema().inTemplateInstantiation())
13841+
Class->setLambdaInstantiatingContextDecl(
13842+
getSema().CodeSynthesisContexts.back().Entity);
1384013843
}
1384113844

1384213845
// FIXME: Sema's lambda-building mechanism expects us to push an expression

clang/test/SemaTemplate/concepts-lambda.cpp

+39
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,45 @@ void foo() {
150150
}
151151
} // namespace ReturnTypeRequirementInLambda
152152

153+
namespace GH70601 {
154+
155+
template <class>
156+
concept C = true;
157+
158+
template <class T, class U>
159+
concept D = C<T> && C<U>;
160+
161+
template <class T>
162+
auto declval() -> decltype(T());
163+
164+
template <class T>
165+
struct S {
166+
template <class U>
167+
using Type = decltype([]<C V>(V) {
168+
return []<D<V> W> {
169+
return W();
170+
}.template operator()<V>();
171+
}(U()));
172+
173+
template <C U>
174+
using ValueType = decltype([]<D<U> V> {
175+
return V();
176+
}.template operator()<U>());
177+
178+
// template <C U>
179+
// using LambdaType = decltype([]<D<U> V> {
180+
// return V();
181+
// });
182+
183+
// using IndirectValueType = decltype(declval<LambdaType<T>>().template operator()<T>());
184+
};
185+
186+
static_assert(__is_same(S<int>::Type<int>, int));
187+
static_assert(__is_same(S<int>::ValueType<float>, float));
188+
// static_assert(__is_same(S<char>::IndirectValueType, char));
189+
190+
}
191+
153192
namespace GH73418 {
154193
void foo() {
155194
int x;

0 commit comments

Comments
 (0)