Author: Younan Zhang Date: 2024-10-15T12:52:31+08:00 New Revision: 3733b0cff314e1427b1a905e6e7438b536f9a96d
URL: https://github.com/llvm/llvm-project/commit/3733b0cff314e1427b1a905e6e7438b536f9a96d DIFF: https://github.com/llvm/llvm-project/commit/3733b0cff314e1427b1a905e6e7438b536f9a96d.diff LOG: [Clang] Fix a DeclContext mismatch when parsing nested lambda parameters (#112177) When parsing its function parameters, we don't change the CurContext to the lambda's function declaration. However, CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures() has not yet adapted to such behavior when nested lambdas come into play. Consider the following case, struct Foo {}; template <int, Foo f> struct Arr {}; constexpr void foo() { constexpr Foo F; [&]<int I>() { [&](Arr<I, F>) {}; }.template operator()<42>(); } As per [basic.def.odr]p5.2, the use of F constitutes an ODR-use. And per [basic.def.odr]p10, F should be ODR-usable in that interleaving scope. We failed to accept the case because the call to tryCaptureVariable() in getStackIndexOfNearestEnclosingCaptureCapableLambda() suggested that F is needlessly captureable. That was due to a missed handling for AfterParameterList in FunctionScopeIndexToStopAt, where it still presumed DC and LSI matched. Fixes #47400 Fixes #90896 Added: Modified: clang/docs/ReleaseNotes.rst clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/SemaCXX/lambda-capture-type-deduction.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index b430b2b0ee3187..21e25fc71bbb17 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -509,10 +509,12 @@ Bug Fixes to C++ Support a class template. (#GH102320) - Fix a crash when parsing a pseudo destructor involving an invalid type. (#GH111460) - Fixed an assertion failure when invoking recovery call expressions with explicit attributes - and undeclared templates. (#GH107047, #GH49093) + and undeclared templates. (#GH107047), (#GH49093) - Clang no longer crashes when a lambda contains an invalid block declaration that contains an unexpanded parameter pack. (#GH109148) - Fixed overload handling for object parameters with top-level cv-qualifiers in explicit member functions (#GH100394) +- Fixed a bug in lambda captures where ``constexpr`` class-type objects were not properly considered ODR-used in + certain situations. (#GH47400), (#GH90896) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 48f4029d873b94..044f56f2af71bf 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -18865,7 +18865,17 @@ bool Sema::tryCaptureVariable( // We need to sync up the Declaration Context with the // FunctionScopeIndexToStopAt if (FunctionScopeIndexToStopAt) { + assert(!FunctionScopes.empty() && "No function scopes to stop at?"); unsigned FSIndex = FunctionScopes.size() - 1; + // When we're parsing the lambda parameter list, the current DeclContext is + // NOT the lambda but its parent. So move away the current LSI before + // aligning DC and FunctionScopeIndexToStopAt. + if (auto *LSI = dyn_cast<LambdaScopeInfo>(FunctionScopes[FSIndex]); + FSIndex && LSI && !LSI->AfterParameterList) + --FSIndex; + assert(MaxFunctionScopesIndex <= FSIndex && + "FunctionScopeIndexToStopAt should be no greater than FSIndex into " + "FunctionScopes."); while (FSIndex != MaxFunctionScopesIndex) { DC = getLambdaAwareParentOfDeclContext(DC); --FSIndex; diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index d39a545b66c151..90e06b5411da77 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -8686,7 +8686,7 @@ static void CheckIfAnyEnclosingLambdasMustCaptureAnyPotentialCaptures( while (isa_and_nonnull<CapturedDecl>(DC)) DC = DC->getParent(); assert( - CurrentLSI->CallOperator == DC && + (CurrentLSI->CallOperator == DC || !CurrentLSI->AfterParameterList) && "The current call operator must be synchronized with Sema's CurContext"); #endif // NDEBUG diff --git a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp index 7bf36a6a9cab73..a86f3018989927 100644 --- a/clang/test/SemaCXX/lambda-capture-type-deduction.cpp +++ b/clang/test/SemaCXX/lambda-capture-type-deduction.cpp @@ -297,3 +297,25 @@ void __trans_tmp_1() { } } + +namespace GH47400 { + +struct Foo {}; + +template <int, Foo> struct Arr {}; + +template <int> struct S {}; + +constexpr void foo() { + constexpr Foo f; + [&]<int is>() { + [&](Arr<is, f>) {}({}); // f constitutes an ODR-use + }.template operator()<42>(); + + constexpr int C = 1; + [] { + [](S<C>) { }({}); // ... while C doesn't + }(); +} + +} // namespace GH47400 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits