[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 30 06:47:01 PDT 2024
https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/86960
>From 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at 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 <yronglin777 at 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.
More information about the cfe-commits
mailing list