https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/86960
>From 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 Mon Sep 17 00:00:00 2001 From: yronglin <yronglin...@gmail.com> 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 <yronglin...@gmail.com> --- 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