Author: Younan Zhang Date: 2025-08-20T00:56:56+08:00 New Revision: 0732693d81975d92399ec6b63823ac27c83ab9fb
URL: https://github.com/llvm/llvm-project/commit/0732693d81975d92399ec6b63823ac27c83ab9fb DIFF: https://github.com/llvm/llvm-project/commit/0732693d81975d92399ec6b63823ac27c83ab9fb.diff LOG: Revert "[Clang] Only remove lambda scope after computing evaluation context" (#154382) Revert due to breakage as reported in https://github.com/llvm/llvm-project/pull/154106#discussion_r2285824084 Reverts llvm/llvm-project#154106 Added: Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Sema/Sema.h clang/lib/Sema/SemaDecl.cpp clang/lib/Sema/SemaLambda.cpp clang/lib/Sema/TreeTransform.h clang/test/SemaCXX/cxx2b-consteval-propagate.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index a8dc5352fcbb4..b86a9c437ffb1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -225,7 +225,6 @@ Bug Fixes to C++ Support - Diagnose binding a reference to ``*nullptr`` during constant evaluation. (#GH48665) - Suppress ``-Wdeprecated-declarations`` in implicitly generated functions. (#GH147293) - Fix a crash when deleting a pointer to an incomplete array (#GH150359). -- Fixed a mismatched lambda scope bug when propagating up ``consteval`` within nested lambdas. (#GH145776) - Fix an assertion failure when expression in assumption attribute (``[[assume(expr)]]``) creates temporary objects. - Fix the dynamic_cast to final class optimization to correctly handle diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 098fe277c2b15..da9070842694e 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4176,15 +4176,8 @@ class Sema final : public SemaBase { /// return statement in the scope of a variable has the same NRVO candidate, /// that candidate is an NRVO variable. void computeNRVO(Stmt *Body, sema::FunctionScopeInfo *Scope); - - /// Performs semantic analysis at the end of a function body. - /// - /// \param RetainFunctionScopeInfo If \c true, the client is responsible for - /// releasing the associated \p FunctionScopeInfo. This is useful when - /// building e.g. LambdaExprs. - Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, - bool IsInstantiation = false, - bool RetainFunctionScopeInfo = false); + Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body); + Decl *ActOnFinishFunctionBody(Decl *Decl, Stmt *Body, bool IsInstantiation); Decl *ActOnSkippedFunctionBody(Decl *Decl); void ActOnFinishInlineFunctionDef(FunctionDecl *D); @@ -6881,23 +6874,23 @@ class Sema final : public SemaBase { assert(!ExprEvalContexts.empty() && "Must be in an expression evaluation context"); return ExprEvalContexts.back(); - } + }; ExpressionEvaluationContextRecord ¤tEvaluationContext() { assert(!ExprEvalContexts.empty() && "Must be in an expression evaluation context"); return ExprEvalContexts.back(); - } + }; ExpressionEvaluationContextRecord &parentEvaluationContext() { assert(ExprEvalContexts.size() >= 2 && "Must be in an expression evaluation context"); return ExprEvalContexts[ExprEvalContexts.size() - 2]; - } + }; const ExpressionEvaluationContextRecord &parentEvaluationContext() const { return const_cast<Sema *>(this)->parentEvaluationContext(); - } + }; bool isAttrContext() const { return ExprEvalContexts.back().ExprContext == @@ -9147,7 +9140,8 @@ class Sema final : public SemaBase { /// Complete a lambda-expression having processed and attached the /// lambda body. - ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc); + ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, + sema::LambdaScopeInfo *LSI); /// Get the return type to use for a lambda's conversion function(s) to /// function pointer type, given the type of the call operator. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 5e62c0cf01510..98485cf9e72be 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -16228,6 +16228,10 @@ Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { return Decl; } +Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { + return ActOnFinishFunctionBody(D, BodyArg, /*IsInstantiation=*/false); +} + /// RAII object that pops an ExpressionEvaluationContext when exiting a function /// body. class ExitFunctionBodyRAII { @@ -16298,8 +16302,8 @@ void Sema::CheckCoroutineWrapper(FunctionDecl *FD) { Diag(FD->getLocation(), diag::err_coroutine_return_type) << RD; } -Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation, - bool RetainFunctionScopeInfo) { +Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, + bool IsInstantiation) { FunctionScopeInfo *FSI = getCurFunction(); FunctionDecl *FD = dcl ? dcl->getAsFunction() : nullptr; @@ -16756,8 +16760,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation, if (!IsInstantiation) PopDeclContext(); - if (!RetainFunctionScopeInfo) - PopFunctionScopeInfo(ActivePolicy, dcl); + PopFunctionScopeInfo(ActivePolicy, dcl); // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index f09f1ad44ccec..0d891fc08c207 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1968,15 +1968,14 @@ ExprResult Sema::BuildCaptureInit(const Capture &Cap, } ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body) { - LambdaScopeInfo &LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); + LambdaScopeInfo LSI = *cast<LambdaScopeInfo>(FunctionScopes.back()); if (LSI.CallOperator->hasAttr<SYCLKernelEntryPointAttr>()) SYCL().CheckSYCLEntryPointFunctionDecl(LSI.CallOperator); - ActOnFinishFunctionBody(LSI.CallOperator, Body, /*IsInstantiation=*/false, - /*RetainFunctionScopeInfo=*/true); + ActOnFinishFunctionBody(LSI.CallOperator, Body); - return BuildLambdaExpr(StartLoc, Body->getEndLoc()); + return BuildLambdaExpr(StartLoc, Body->getEndLoc(), &LSI); } static LambdaCaptureDefault @@ -2133,9 +2132,8 @@ ConstructFixItRangeForUnusedCapture(Sema &S, SourceRange CaptureRange, return SourceRange(FixItStart, FixItEnd); } -ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, - SourceLocation EndLoc) { - LambdaScopeInfo *LSI = cast<LambdaScopeInfo>(FunctionScopes.back()); +ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, + LambdaScopeInfo *LSI) { // Collect information from the lambda scope. SmallVector<LambdaCapture, 4> Captures; SmallVector<Expr *, 4> CaptureInits; @@ -2172,12 +2170,6 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, PopExpressionEvaluationContext(); - sema::AnalysisBasedWarnings::Policy WP = - AnalysisWarnings.getPolicyInEffectAt(EndLoc); - // We cannot release LSI until we finish computing captures, which - // requires the scope to be popped. - PoppedFunctionScopePtr _ = PopFunctionScopeInfo(&WP, LSI->CallOperator); - // True if the current capture has a used capture or default before it. bool CurHasPreviousCapture = CaptureDefault != LCD_None; SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 7f0b24ecb7e20..51f58e35a1ef4 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -4051,7 +4051,7 @@ class TreeTransform { PVD->getUninstantiatedDefaultArg() ->containsUnexpandedParameterPack(); } - return getSema().BuildLambdaExpr(StartLoc, EndLoc); + return getSema().BuildLambdaExpr(StartLoc, EndLoc, LSI); } /// Build an empty C++1z fold-expression with the given operator. @@ -15712,9 +15712,12 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { return ExprError(); } + // Copy the LSI before ActOnFinishFunctionBody removes it. + // FIXME: This is dumb. Store the lambda information somewhere that outlives + // the call operator. + auto LSICopy = *LSI; getSema().ActOnFinishFunctionBody(NewCallOperator, Body.get(), - /*IsInstantiation=*/true, - /*RetainFunctionScopeInfo=*/true); + /*IsInstantiation*/ true); SavedContext.pop(); // Recompute the dependency of the lambda so that we can defer the lambda call @@ -15750,11 +15753,11 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // *after* the substitution in case we can't decide the dependency // so early, e.g. because we want to see if any of the *substituted* // parameters are dependent. - DependencyKind = getDerived().ComputeLambdaDependency(LSI); + DependencyKind = getDerived().ComputeLambdaDependency(&LSICopy); Class->setLambdaDependencyKind(DependencyKind); return getDerived().RebuildLambdaExpr(E->getBeginLoc(), - Body.get()->getEndLoc(), LSI); + Body.get()->getEndLoc(), &LSICopy); } template<typename Derived> diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp index 6cf0e0251ab62..c4cfd9398920a 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -610,19 +610,3 @@ namespace GH135281 { void (*ff)() = f2<B>; // expected-note {{instantiation of function template specialization}} } #endif - -namespace GH145776 { - -void runtime_only() {} -consteval void comptime_only() {} - -void fn() { - []() { - runtime_only(); - []() { - &comptime_only; - }(); - }(); -} - -} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits