diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 5b2a6349a5b15..acce35e231e71 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -268,11 +268,6 @@ Bug Fixes to C++ Support - Fix crash when parsing the requires clause of some generic lambdas. (`#64689 `_) -- Fix crash when the trailing return type of a generic and dependent - lambda refers to an init-capture. - (`#65067 `_) and - (`#63675 `_). - Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ - Fixed an import failure of recursive friend class template. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4fd0e6bd5982a..5fdca93c66ab5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -7352,14 +7352,6 @@ class Sema final { sema::LambdaScopeInfo *RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator); - class LambdaScopeForCallOperatorInstantiationRAII - : private FunctionScopeRAII { - public: - LambdaScopeForCallOperatorInstantiationRAII( - Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, - LocalInstantiationScope &Scope); - }; - /// Check whether the given expression is a valid constraint expression. /// A diagnostic is emitted if it is not, false is returned, and /// PossibleNonPrimary will be set to true if the failure might be due to a diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index d1fa8e7831225..fa3dadf68229e 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -600,6 +600,11 @@ bool Sema::SetupConstraintScope( if (addInstantiatedParametersToScope(FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL)) return true; + // Make sure the captures are also added to the instantiation scope. + if (isLambdaCallOperator(FD) && + addInstantiatedCapturesToScope(FD, FromMemTempl->getTemplatedDecl(), + Scope, MLTAL)) + return true; } return false; @@ -624,6 +629,11 @@ bool Sema::SetupConstraintScope( // child-function. if (addInstantiatedParametersToScope(FD, InstantiatedFrom, Scope, MLTAL)) return true; + + // Make sure the captures are also added to the instantiation scope. + if (isLambdaCallOperator(FD) && + addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL)) + return true; } return false; @@ -702,8 +712,20 @@ bool Sema::CheckFunctionConstraints(const FunctionDecl *FD, } CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); - LambdaScopeForCallOperatorInstantiationRAII LambdaScope( - *this, const_cast(FD), *MLTAL, Scope); + // When checking the constraints of a lambda, we need to restore a + // LambdaScopeInfo populated with correct capture information so that the type + // of a variable referring to a capture is correctly const-adjusted. + FunctionScopeRAII FuncScope(*this); + if (isLambdaCallOperator(FD)) { + LambdaScopeInfo *LSI = RebuildLambdaScopeInfo( + const_cast(cast(FD))); + // Constraints are checked from the parent context of the lambda, so we set + // AfterParameterList to false, so that `tryCaptureVariable` finds + // explicit captures in the appropriate context. + LSI->AfterParameterList = false; + } else { + FuncScope.disable(); + } return CheckConstraintSatisfaction( FD, {FD->getTrailingRequiresClause()}, *MLTAL, @@ -891,10 +913,15 @@ bool Sema::CheckInstantiatedFunctionTemplateConstraints( ThisQuals = Method->getMethodQualifiers(); Record = Method->getParent(); } - CXXThisScopeRAII ThisScope(*this, Record, ThisQuals, Record != nullptr); - LambdaScopeForCallOperatorInstantiationRAII LambdaScope( - *this, const_cast(Decl), *MLTAL, Scope); + FunctionScopeRAII FuncScope(*this); + + if (isLambdaCallOperator(Decl)) { + LambdaScopeInfo *LSI = RebuildLambdaScopeInfo(cast(Decl)); + LSI->AfterParameterList = false; + } else { + FuncScope.disable(); + } llvm::SmallVector Converted; return CheckConstraintSatisfaction(Template, TemplateAC, Converted, *MLTAL, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index d6e090ee496eb..d94366dac102a 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15380,10 +15380,6 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) { LSI->CallOperator = CallOperator; LSI->Lambda = LambdaClass; LSI->ReturnType = CallOperator->getReturnType(); - // This function in calls in situation where the context of the call operator - // is not entered, so we set AfterParameterList to false, so that - // `tryCaptureVariable` finds explicit captures in the appropriate context. - LSI->AfterParameterList = false; const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault(); if (LCD == LCD_None) diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 1702ddb3ee0fb..5256d91a19a0d 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -20,7 +20,6 @@ #include "clang/Sema/ScopeInfo.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/SemaLambda.h" -#include "clang/Sema/Template.h" #include "llvm/ADT/STLExtras.h" #include using namespace clang; @@ -2255,34 +2254,3 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, return BuildBlock; } - -Sema::LambdaScopeForCallOperatorInstantiationRAII:: - LambdaScopeForCallOperatorInstantiationRAII( - Sema &SemasRef, FunctionDecl *FD, MultiLevelTemplateArgumentList MLTAL, - LocalInstantiationScope &Scope) - : FunctionScopeRAII(SemasRef) { - if (!isLambdaCallOperator(FD)) { - FunctionScopeRAII::disable(); - return; - } - - if (FD->isTemplateInstantiation() && FD->getPrimaryTemplate()) { - FunctionTemplateDecl *PrimaryTemplate = FD->getPrimaryTemplate(); - if (const auto *FromMemTempl = - PrimaryTemplate->getInstantiatedFromMemberTemplate()) { - SemasRef.addInstantiatedCapturesToScope( - FD, FromMemTempl->getTemplatedDecl(), Scope, MLTAL); - } - } - - else if (FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || - FD->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) { - FunctionDecl *InstantiatedFrom = - FD->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization - ? FD->getInstantiatedFromMemberFunction() - : FD->getInstantiatedFromDecl(); - SemasRef.addInstantiatedCapturesToScope(FD, InstantiatedFrom, Scope, MLTAL); - } - - SemasRef.RebuildLambdaScopeInfo(cast(FD)); -} diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 37a7d6204413a..63f022d5c2ff0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -2426,9 +2426,6 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( cast(Owner)->isDefinedOutsideFunctionOrMethod()); LocalInstantiationScope Scope(SemaRef, MergeWithParentScope); - Sema::LambdaScopeForCallOperatorInstantiationRAII LambdaScope( - SemaRef, const_cast(D), TemplateArgs, Scope); - // Instantiate enclosing template arguments for friends. SmallVector TempParamLists; unsigned NumTempParamLists = 0; diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index a075ade1adb7b..7323140bc336b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -12325,7 +12325,7 @@ TreeTransform::TransformCXXNullPtrLiteralExpr( template ExprResult TreeTransform::TransformCXXThisExpr(CXXThisExpr *E) { - QualType T = getDerived().TransformType(E->getType()); + QualType T = getSema().getCurrentThisType(); if (!getDerived().AlwaysRebuild() && T == E->getType()) { // Mark it referenced in the new context regardless. diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp index 7bf36a6a9cab7..9855122c96272 100644 --- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp +++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp @@ -260,40 +260,3 @@ void f(int) { void test() { f(0); } } - -namespace GH65067 { - -template class a { -public: - template void c(b f) { d(f)(0); } - template auto d(b f) { - return [f = f](auto arg) -> a { return {}; }; - } -}; -a e; -auto fn1() { - e.c([](int) {}); -} - -} - -namespace GH63675 { - -template _Tp __declval(); -struct __get_tag { - template void operator()(_Tag); -}; -template struct __basic_sender { - using __tag_t = decltype(__declval<_ImplFn>()(__declval<__get_tag>())); - _ImplFn __impl_; -}; -auto __make_basic_sender = []( - _Children... __children) { - return __basic_sender{[... __children = __children]( - _Fun __fun) -> decltype(__fun(__children...)) {}}; -}; -void __trans_tmp_1() { - __make_basic_sender(__trans_tmp_1); -} - -}