diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 20bd27ad52f577..01c7899e36c932 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -764,6 +764,8 @@ Bug Fixes to C++ Support - Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385) - Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659) - Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205) +- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda + captures at the end of a full expression. (#GH115931) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index ba574307055c6b..c4bb73b2924bc9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -15519,10 +15519,25 @@ 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 + // When this function is called in situation where the context of the call + // operator is not entered, we set AfterParameterList to false, so that // `tryCaptureVariable` finds explicit captures in the appropriate context. - LSI->AfterParameterList = false; + // There is also at least a situation as in FinishTemplateArgumentDeduction(), + // where we would set the CurContext to the lambda operator before + // substituting into it. In this case the flag needs to be true such that + // tryCaptureVariable can correctly handle potential captures thereof. + LSI->AfterParameterList = CurContext == CallOperator; + + // GLTemplateParameterList is necessary for getCurGenericLambda() which is + // used at the point of dealing with potential captures. + // + // We don't use LambdaClass->isGenericLambda() because this value doesn't + // flip for instantiated generic lambdas, where no FunctionTemplateDecls are + // associated. (Technically, we could recover that list from their + // instantiation patterns, but for now, the GLTemplateParameterList seems + // unnecessary in these cases.) + if (FunctionTemplateDecl *FTD = CallOperator->getDescribedFunctionTemplate()) + LSI->GLTemplateParameterList = FTD->getTemplateParameters(); const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault(); if (LCD == LCD_None) diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp index a86f3018989927..234cb6806f041a 100644 --- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp +++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp @@ -298,6 +298,22 @@ void __trans_tmp_1() { } +namespace GH115931 { + +struct Range {}; + +template +struct LengthPercentage {}; + +void reflectSum() { + Range resultR; + [&] (auto) -> LengthPercentage { + return {}; + }(0); +} + +} // namespace GH115931 + namespace GH47400 { struct Foo {};