[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)

2024-04-02 Thread via cfe-commits

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)

2024-03-30 Thread via cfe-commits

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)

2024-03-28 Thread via cfe-commits

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)

2024-03-28 Thread via cfe-commits

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;
-