diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1137,11 +1137,10 @@ } } - // 2) We've run out of ScopeInfos but check if CurDC is a lambda (which can - // happen during instantiation of its nested generic lambda call operator) - if (isLambdaCallOperator(CurDC)) { - assert(CurLSI && "While computing 'this' capture-type for a generic " - "lambda, we must have a corresponding LambdaScopeInfo"); + // 2) We've run out of ScopeInfos but check 1. if CurDC is a lambda (which + // can happen during instantiation of its nested generic lambda call + // operator); 2. if we're in a lambda scope (lambda body). + if (CurLSI && isLambdaCallOperator(CurDC)) { assert(isGenericLambdaCallOperatorSpecialization(CurLSI->CallOperator) && "While computing 'this' capture-type for a generic lambda, when we " "run out of enclosing LSI's, yet the enclosing DC is a " diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5110,7 +5110,11 @@ for (unsigned i = 0, e = Param->getDepth(); i != e; ++i) TemplateArgLists.addOuterTemplateArguments(None); - Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext()); + bool ForLambdaCallOperator = false; + if (const auto *Rec = dyn_cast(Template->getDeclContext())) + ForLambdaCallOperator = Rec->isLambda(); + Sema::ContextRAII SavedContext(SemaRef, Template->getDeclContext(), + !ForLambdaCallOperator); ArgType = SemaRef.SubstType(ArgType, TemplateArgLists, Param->getDefaultArgumentLoc(), Param->getDeclName()); diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2858,9 +2858,24 @@ return Sema::TDK_Incomplete; } - TemplateArgumentLoc DefArg = S.SubstDefaultTemplateArgumentIfAvailable( - TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder, - HasDefaultArg); + TemplateArgumentLoc DefArg; + { + Qualifiers ThisTypeQuals; + CXXRecordDecl *ThisContext = nullptr; + if (auto *Rec = dyn_cast(TD->getDeclContext())) + if (Rec->isLambda()) + if (auto *Method = dyn_cast(Rec->getDeclContext())) { + ThisContext = Method->getParent(); + ThisTypeQuals = Method->getMethodQualifiers(); + } + + Sema::CXXThisScopeRAII ThisScope(S, ThisContext, ThisTypeQuals, + S.getLangOpts().CPlusPlus17); + + DefArg = S.SubstDefaultTemplateArgumentIfAvailable( + TD, TD->getLocation(), TD->getSourceRange().getEnd(), Param, Builder, + HasDefaultArg); + } // If there was no default argument, deduction is incomplete. if (DefArg.getArgument().isNull()) { diff --git a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp --- a/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp +++ b/clang/test/SemaCXX/cxx1z-lambda-star-this.cpp @@ -298,3 +298,13 @@ } // namespace PR32831 +namespace PR45881 { +struct A { + void f(); +}; +int id(A*); +void A::f() { + auto z = [*this](auto z2, decltype(z2(this)) z3){}; + z(id,3); +} +} // namespace PR45881 diff --git a/clang/test/SemaCXX/cxx20-lambda-decltype-this.cpp b/clang/test/SemaCXX/cxx20-lambda-decltype-this.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/cxx20-lambda-decltype-this.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -emit-llvm-only %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fdelayed-template-parsing %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fms-extensions %s +// RUN: %clang_cc1 -std=c++2a -fsyntax-only -fdelayed-template-parsing -fms-extensions %s + +namespace PR45881 { +struct A { + void f(); +}; +int id(A*); +void A::f() { + auto z = [*this](auto z2, decltype(z2(this)) z3){}; + z(id,3); +} + +struct B { + void f(); +}; +void B::f() { + auto z = [](){return 0;}; + z.template operator()(); +} + +struct C { + void f(); +}; +void C::f() { + auto z = [](){return 0;}; + z.template operator()(); +} +} // namespace PR45881