Skip to content

Commit 61d1cce

Browse files
author
Yuanfang Chen
committed
PR45881: Properly use CXXThisOverride for templated lambda
- `this` used in lambda expression parameter declarations needs no capture. - Set up CXXThisOverride for default template arguments of a lambda. A similar fix to this is c3d2ebb. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D102531
1 parent 79c00d3 commit 61d1cce

File tree

5 files changed

+68
-9
lines changed

5 files changed

+68
-9
lines changed

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1137,11 +1137,10 @@ static QualType adjustCVQualifiersForCXXThisWithinLambda(
11371137
}
11381138
}
11391139

1140-
// 2) We've run out of ScopeInfos but check if CurDC is a lambda (which can
1141-
// happen during instantiation of its nested generic lambda call operator)
1142-
if (isLambdaCallOperator(CurDC)) {
1143-
assert(CurLSI && "While computing 'this' capture-type for a generic "
1144-
"lambda, we must have a corresponding LambdaScopeInfo");
1140+
// 2) We've run out of ScopeInfos but check 1. if CurDC is a lambda (which
1141+
// can happen during instantiation of its nested generic lambda call
1142+
// operator); 2. if we're in a lambda scope (lambda body).
1143+
if (CurLSI && isLambdaCallOperator(CurDC)) {
11451144
assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator) &&
11461145
"While computing 'this' capture-type for a generic lambda, when we "
11471146
"run out of enclosing LSI's, yet the enclosing DC is a "

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5110,7 +5110,11 @@ SubstDefaultTemplateArgument(Sema &SemaRef,
51105110
for (unsigned i = 0, e = Param->getDepth(); i != e; ++i)
51115111
TemplateArgLists.addOuterTemplateArguments(None);
51125112

5113-
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext());
5113+
bool ForLambdaCallOperator = false;
5114+
if (const auto *Rec = dyn_cast<CXXRecordDecl>(Template->getDeclContext()))
5115+
ForLambdaCallOperator = Rec->isLambda();
5116+
Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(),
5117+
!ForLambdaCallOperator);
51145118
ArgType =
51155119
SemaRef.SubstType(ArgType, TemplateArgLists,
51165120
Param->getDefaultArgumentLoc(), Param->getDeclName());

clang/lib/Sema/SemaTemplateDeduction.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,9 +2858,24 @@ static Sema::TemplateDeductionResult ConvertDeducedTemplateArguments(
28582858
return Sema::TDK_Incomplete;
28592859
}
28602860

2861-
TemplateArgumentLoc DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
2862-
TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
2863-
HasDefaultArg);
2861+
TemplateArgumentLoc DefArg;
2862+
{
2863+
Qualifiers ThisTypeQuals;
2864+
CXXRecordDecl *ThisContext = nullptr;
2865+
if (auto *Rec = dyn_cast<CXXRecordDecl>(TD->getDeclContext()))
2866+
if (Rec->isLambda())
2867+
if (auto *Method = dyn_cast<CXXMethodDecl>(Rec->getDeclContext())) {
2868+
ThisContext = Method->getParent();
2869+
ThisTypeQuals = Method->getMethodQualifiers();
2870+
}
2871+
2872+
Sema::CXXThisScopeRAII ThisScope(S, ThisContext, ThisTypeQuals,
2873+
S.getLangOpts().CPlusPlus17);
2874+
2875+
DefArg = S.SubstDefaultTemplateArgumentIfAvailable(
2876+
TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder,
2877+
HasDefaultArg);
2878+
}
28642879

28652880
// If there was no default argument, deduction is incomplete.
28662881
if (DefArg.getArgument().isNull()) {

clang/test/SemaCXX/cxx1z-lambda-star-this.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,13 @@ class A {
298298

299299
} // namespace PR32831
300300

301+
namespace PR45881 {
302+
struct A {
303+
void f();
304+
};
305+
int id(A*);
306+
void A::f() {
307+
auto z = [*this](auto z2, decltype(z2(this)) z3){};
308+
z(id,3);
309+
}
310+
} // namespace PR45881
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -emit-llvm-only %s
2+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fdelayed-template-parsing %s
3+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fms-extensions %s
4+
// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fdelayed-template-parsing -fms-extensions %s
5+
6+
namespace PR45881 {
7+
struct A {
8+
void f();
9+
};
10+
int id(A*);
11+
void A::f() {
12+
auto z = [*this](auto z2, decltype(z2(this)) z3){};
13+
z(id,3);
14+
}
15+
16+
struct B {
17+
void f();
18+
};
19+
void B::f() {
20+
auto z = []<typename TT, typename TTT=decltype(TT()(this))>(){return 0;};
21+
z.template operator()<int(*)(B*)>();
22+
}
23+
24+
struct C {
25+
void f();
26+
};
27+
void C::f() {
28+
auto z = []<typename TT, decltype(TT()(this)) n>(){return 0;};
29+
z.template operator()<int(*)(C*), 8>();
30+
}
31+
} // namespace PR45881

0 commit comments

Comments
 (0)