[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/86960 >From 2e05cb427d245261c779725f355ec93f4989939b Mon Sep 17 00:00:00 2001 From: yronglin Date: Tue, 2 Apr 2024 23:47:33 +0800 Subject: [PATCH] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 Signed-off-by: yronglin --- clang/lib/CodeGen/CGExpr.cpp| 48 - clang/lib/CodeGen/CGStmt.cpp| 12 clang/lib/CodeGen/CodeGenFunction.h | 31 +++ clang/lib/Sema/SemaExpr.cpp | 9 -- clang/lib/Sema/SemaInit.cpp | 7 +++-- 5 files changed, 80 insertions(+), 27 deletions(-) diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 54432353e7420d..b92a2910f8c8b0 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -268,9 +268,9 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E, llvm_unreachable("bad evaluation kind"); } -static void -pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, - const Expr *E, Address ReferenceTemporary) { +void CodeGenFunction::pushTemporaryCleanup(const MaterializeTemporaryExpr *M, + const Expr *E, + Address ReferenceTemporary) { // Objective-C++ ARC: // If we are binding a reference to a temporary that has ownership, we // need to perform retain/release operations on the temporary. @@ -305,9 +305,9 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, CleanupKind CleanupKind; if (Lifetime == Qualifiers::OCL_Strong) { const ValueDecl *VD = M->getExtendingDecl(); - bool Precise = - VD && isa(VD) && VD->hasAttr(); - CleanupKind = CGF.getARCCleanupKind(); + bool Precise = isa_and_nonnull(VD) && + VD->hasAttr(); + CleanupKind = getARCCleanupKind(); Destroy = Precise ? &CodeGenFunction::destroyARCStrongPrecise : &CodeGenFunction::destroyARCStrongImprecise; } else { @@ -317,11 +317,11 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, Destroy = &CodeGenFunction::destroyARCWeak; } if (Duration == SD_FullExpression) - CGF.pushDestroy(CleanupKind, ReferenceTemporary, + pushDestroy(CleanupKind, ReferenceTemporary, M->getType(), *Destroy, CleanupKind & EHCleanup); else - CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary, + pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary, M->getType(), *Destroy, CleanupKind & EHCleanup); return; @@ -352,32 +352,32 @@ pushTemporaryCleanup(CodeGenFunction &CGF, const MaterializeTemporaryExpr *M, llvm::FunctionCallee CleanupFn; llvm::Constant *CleanupArg; if (E->getType()->isArrayType()) { - CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper( + CleanupFn = CodeGenFunction(CGM).generateDestroyHelper( ReferenceTemporary, E->getType(), - CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions, + CodeGenFunction::destroyCXXObject, getLangOpts().Exceptions, dyn_cast_or_null(M->getExtendingDecl())); - CleanupArg = llvm::Constant::getNullValue(CGF.Int8PtrTy); + CleanupArg = llvm::Constant::getNullValue(Int8PtrTy); } else { - CleanupFn = CGF.CGM.getAddrAndTypeOfCXXStructor( + CleanupFn = CGM.getAddrAndTypeOfCXXStructor( GlobalDecl(ReferenceTemporaryDtor, Dtor_Complete)); - CleanupArg = cast(ReferenceTemporary.emitRawPointer(CGF)); + CleanupArg = cast(ReferenceTemporary.emitRawPointer(*this)); } -CGF.CGM.getCXXABI().registerGlobalDtor( -CGF, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); +CGM.getCXXABI().registerGlobalDtor( +*this, *cast(M->getExtendingDecl()), CleanupFn, CleanupArg); break; } case SD_FullExpression: -CGF.pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(), +pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(), CodeGenFunction::destroyCXXObject, -CGF.getLangOpts().Exceptions); +getLangOpts().Exceptions); break; case SD_Automatic: -CGF.pushLifetimeExtendedDestroy(NormalAndEHCleanup, +pushLifetimeExtendedDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(), CodeGenFunction::destroyCXXObject, -CGF.getLangOpts().Exceptions); +getLangOpts().Exceptions); break; case SD_Dynamic: @@
[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/86960 >From 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 Mon Sep 17 00:00:00 2001 From: yronglin Date: Thu, 28 Mar 2024 22:02:16 +0800 Subject: [PATCH] [WIP][Clang] Extend lifetime of the temporary in default member init expression Signed-off-by: yronglin --- clang/lib/Sema/SemaExpr.cpp | 9 ++--- clang/lib/Sema/SemaInit.cpp | 27 --- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5f03b981428251..3c923d7c002feb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6372,7 +6372,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6407,12 +6407,15 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; - +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); +keepInMaterializeTemporaryObjectContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; runWithSufficientStackSpace(Loc, [&] { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index aa470adb30b47f..85baf52e1f074c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8052,11 +8052,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, enum PathLifetimeKind { /// Lifetime-extend along this path. Extend, - /// We should lifetime-extend, but we don't because (due to technical - /// limitations) we can't. This happens for default member initializers, - /// which we don't clone for every use, so we don't have a unique - /// MaterializeTemporaryExpr to update. - ShouldExtend, + /// Do not lifetime extend along this path. NoExtend }; @@ -8067,9 +8063,7 @@ static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { -if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) - Kind = PathLifetimeKind::ShouldExtend; -else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) +if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) return PathLifetimeKind::NoExtend; } return Kind; @@ -8182,6 +8176,12 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, switch (shouldLifetimeExtendThroughPath(Path)) { case PathLifetimeKind::Extend: + +// If in a lifetime-extending context, delay extending action. +// e.g. Delayed lifetime extending until building for-range-stmt. +if (isInLifetimeExtendingContext()) + return true; + // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. MTE->setExtendingDecl(ExtendingEntity->getDecl(), @@ -8189,17 +8189,6 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Also visit the temporaries lifetime-extended by this initializer. return true; - case PathLifetimeKind::ShouldExtend: -// We're supposed to lifetime-extend the temporary along this path (per -// the resolution of DR1815), but we don't support that yet. -// -// FIXME: Properly handle this situation. Perhaps the easiest approach -// would be to clone the initializer expression on each use that would -// lifetime extend its temporaries. -Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) -<< RK << DiagRange; -break; - case PathLifetimeKind::NoExtend: // If the path goes through the initialization of a variable or field, // it can't possibly reach a temporary created in this full-expression. ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)
github-actions[bot] wrote: :warning: C/C++ code formatter, clang-format found issues in your code. :warning: You can test this locally with the following command: ``bash git-clang-format --diff 49b520856967c2354339d3c2a05fcf1d2d637f30 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 -- clang/lib/Sema/SemaExpr.cpp clang/lib/Sema/SemaInit.cpp `` View the diff from clang-format here. ``diff diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 85baf52e1f..fa44a6fbaa 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8178,7 +8178,7 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, case PathLifetimeKind::Extend: // If in a lifetime-extending context, delay extending action. -// e.g. Delayed lifetime extending until building for-range-stmt. +// e.g. Delayed lifetime extending until building for-range-stmt. if (isInLifetimeExtendingContext()) return true; `` https://github.com/llvm/llvm-project/pull/86960 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)
https://github.com/yronglin created https://github.com/llvm/llvm-project/pull/86960 Fixes https://github.com/llvm/llvm-project/issues/85613. In https://github.com/llvm/llvm-project/pull/76361, we've not implement the lifetime extensions for the temporaries which in `CXXDefaultInitExpr`. As the description in https://github.com/llvm/llvm-project/issues/85613, we should extend lifetime for that. `PathLifetimeKind::ShouldExtend` has been removed, because we already has some machinery to rewrite `CXXDefaultInitExpr`. This PR still work in progress. >From 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 Mon Sep 17 00:00:00 2001 From: yronglin Date: Thu, 28 Mar 2024 22:02:16 +0800 Subject: [PATCH] [WIP][Clang] Extend lifetime of the temporary in default member init expression Signed-off-by: yronglin --- clang/lib/Sema/SemaExpr.cpp | 9 ++--- clang/lib/Sema/SemaInit.cpp | 27 --- 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5f03b981428251..3c923d7c002feb 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6372,7 +6372,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { Expr *Init = nullptr; bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer(); - + bool InLifetimeExtendingContext = isInLifetimeExtendingContext(); EnterExpressionEvaluationContext EvalContext( *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field); @@ -6407,12 +6407,15 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field) { ImmediateCallVisitor V(getASTContext()); if (!NestedDefaultChecking) V.TraverseDecl(Field); - if (V.HasImmediateCalls) { + if (V.HasImmediateCalls || InLifetimeExtendingContext) { ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field, CurContext}; ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer = NestedDefaultChecking; - +// Pass down lifetime extending flag, and collect temporaries in +// CreateMaterializeTemporaryExpr when we rewrite the call argument. +keepInLifetimeExtendingContext(); +keepInMaterializeTemporaryObjectContext(); EnsureImmediateInvocationInDefaultArgs Immediate(*this); ExprResult Res; runWithSufficientStackSpace(Loc, [&] { diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index aa470adb30b47f..85baf52e1f074c 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -8052,11 +8052,7 @@ static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, enum PathLifetimeKind { /// Lifetime-extend along this path. Extend, - /// We should lifetime-extend, but we don't because (due to technical - /// limitations) we can't. This happens for default member initializers, - /// which we don't clone for every use, so we don't have a unique - /// MaterializeTemporaryExpr to update. - ShouldExtend, + /// Do not lifetime extend along this path. NoExtend }; @@ -8067,9 +8063,7 @@ static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) { PathLifetimeKind Kind = PathLifetimeKind::Extend; for (auto Elem : Path) { -if (Elem.Kind == IndirectLocalPathEntry::DefaultInit) - Kind = PathLifetimeKind::ShouldExtend; -else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) +if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit) return PathLifetimeKind::NoExtend; } return Kind; @@ -8182,6 +8176,12 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, switch (shouldLifetimeExtendThroughPath(Path)) { case PathLifetimeKind::Extend: + +// If in a lifetime-extending context, delay extending action. +// e.g. Delayed lifetime extending until building for-range-stmt. +if (isInLifetimeExtendingContext()) + return true; + // Update the storage duration of the materialized temporary. // FIXME: Rebuild the expression instead of mutating it. MTE->setExtendingDecl(ExtendingEntity->getDecl(), @@ -8189,17 +8189,6 @@ void Sema::checkInitializerLifetime(const InitializedEntity &Entity, // Also visit the temporaries lifetime-extended by this initializer. return true; - case PathLifetimeKind::ShouldExtend: -// We're supposed to lifetime-extend the temporary along this path (per -// the resolution of DR1815), but we don't support that yet. -// -// FIXME: Properly handle this situation. Perhaps the easiest approach -// would be to clone the initializer expression on each use that would -// lifetime extend its temporaries. -Diag(DiagLoc, diag::warn_unsupported_lifetime_extension) -<< RK << DiagRange; -