Skip to content

Commit 9ea993f

Browse files
authored
[Clang] Recover GLTemplateParameterList for generic lambdas in RebuildLambdaScopeInfo (#118176)
The NTTP argument appearing inside a trailing return type of a generic lambda would have us check for potential lambda captures, where the function needs GLTemplateParameterList of the current LSI to tell whether the lambda is generic. The lambda scope in this context is rebuilt by the LambdaScopeForCallOperatorInstantiationRAII when substituting the lambda operator during template argument deduction. Thus, I think the template parameter list should be preserved in the rebuilding process, as it seems otherwise innocuous to me. Fixes #115931
1 parent fb14012 commit 9ea993f

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -764,6 +764,8 @@ Bug Fixes to C++ Support
764764
- Fixed an assertion failure caused by using ``consteval`` in condition in consumed analyses. (#GH117385)
765765
- Fix a crash caused by incorrect argument position in merging deduced template arguments. (#GH113659)
766766
- Fixed an assertion failure caused by mangled names with invalid identifiers. (#GH112205)
767+
- Fixed an incorrect lambda scope of generic lambdas that caused Clang to crash when computing potential lambda
768+
captures at the end of a full expression. (#GH115931)
767769

768770
Bug Fixes to AST Handling
769771
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15519,10 +15519,25 @@ LambdaScopeInfo *Sema::RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator) {
1551915519
LSI->CallOperator = CallOperator;
1552015520
LSI->Lambda = LambdaClass;
1552115521
LSI->ReturnType = CallOperator->getReturnType();
15522-
// This function in calls in situation where the context of the call operator
15523-
// is not entered, so we set AfterParameterList to false, so that
15522+
// When this function is called in situation where the context of the call
15523+
// operator is not entered, we set AfterParameterList to false, so that
1552415524
// `tryCaptureVariable` finds explicit captures in the appropriate context.
15525-
LSI->AfterParameterList = false;
15525+
// There is also at least a situation as in FinishTemplateArgumentDeduction(),
15526+
// where we would set the CurContext to the lambda operator before
15527+
// substituting into it. In this case the flag needs to be true such that
15528+
// tryCaptureVariable can correctly handle potential captures thereof.
15529+
LSI->AfterParameterList = CurContext == CallOperator;
15530+
15531+
// GLTemplateParameterList is necessary for getCurGenericLambda() which is
15532+
// used at the point of dealing with potential captures.
15533+
//
15534+
// We don't use LambdaClass->isGenericLambda() because this value doesn't
15535+
// flip for instantiated generic lambdas, where no FunctionTemplateDecls are
15536+
// associated. (Technically, we could recover that list from their
15537+
// instantiation patterns, but for now, the GLTemplateParameterList seems
15538+
// unnecessary in these cases.)
15539+
if (FunctionTemplateDecl *FTD = CallOperator->getDescribedFunctionTemplate())
15540+
LSI->GLTemplateParameterList = FTD->getTemplateParameters();
1552615541
const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault();
1552715542

1552815543
if (LCD == LCD_None)

clang/test/SemaCXX/lambda-capture-type-deduction.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,22 @@ void __trans_tmp_1() {
298298

299299
}
300300

301+
namespace GH115931 {
302+
303+
struct Range {};
304+
305+
template <Range>
306+
struct LengthPercentage {};
307+
308+
void reflectSum() {
309+
Range resultR;
310+
[&] (auto) -> LengthPercentage<resultR> {
311+
return {};
312+
}(0);
313+
}
314+
315+
} // namespace GH115931
316+
301317
namespace GH47400 {
302318

303319
struct Foo {};

0 commit comments

Comments
 (0)