[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-11 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

Thank you for your confirmation, I will add a special-case to ExprWithCleanups 
handling once PR  https://github.com/llvm/llvm-project/pull/87930 
https://github.com/llvm/llvm-project/pull/87933 merged.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

Oh, so it's actually supposed to say "If a temporary expression is bound to a 
reference member from a default member initializer, and that member initializer 
is used by a constructor, the constructor is ill-formed" or something like 
that?  I guess that makes sense in context, but the language could be improved.

Back to the issue we were discussing here, when are the destructors for 
non-lifetime-extended temporaries supposed to run?  If they're supposed to stay 
live for the whole expression, probably the rewriting code in Sema should just 
rewrite out the ExprWithCleanups.

If they're supposed to be destroyed, you might need to add a special-case to 
ExprWithCleanups handling to special-case the cleanups for the temporaries that 
are supposed to be lifetime-extended.  (If you're going to touch this code, 
make sure you're working on latest main, since #85398 landed recently.)

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread Richard Smith via cfe-commits

https://github.com/zygoloid edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread Richard Smith via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

zygoloid wrote:

Thr quoted rule is [class.base.init]/11, and in that context is describing the 
behavior of the initialization of class members in a constructor.

Aggregate initialization is handled by the general rule in [class.temporary] 
but see also the [note in 
[dcl.init.general]](https://eel.is/c++draft/dcl.init#general-16.6.2.2.sentence-8)
 that explicitly mentions this case.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

If you think "A temporary expression bound to a reference member from a default 
member initializer is ill-formed" doesn't refer to this case, what does it 
refer to?

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

I've another separate PR https://github.com/llvm/llvm-project/pull/87933 that 
support lifetime extension of temporary created by aggregate initialization 
using a default member initializer. In this case the temporary `A{}` created by 
aggregate initialization(I've misunderstand here before), I think since DR1815, 
it's well-formed.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

It makes sense that the extra ExprWithCleanups would force the destructor to 
run early, since that's supposed to be the marker for a full-expression.

Do we actually need to handle this case?  Looking at the current standard, it 
says "A temporary expression bound to a reference member from a default member 
initializer is ill-formed", which would seem to imply we should reject any case 
that would require this sort of lifetime extension.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

The problem seems to be caused by C2 `ExprWithCleanups `

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-10 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

The AST of `B{}` looks like the following. As far as I know, when I try to 
debug the code generation of the temporary `Cleanups`, I found the following 
steps.

Let M1 be `MaterializeTemporaryExpr 0x133830b80  'B' xvalue 
extended by Var 0x133830940 '__range1' 'B &&'`
Let M2 be `MaterializeTemporaryExpr 0x1338305f0  'const A' 
lvalue extended by Var 0x133830940 '__range1' 'B &&'`
Let C1 be `ExprWithCleanups 0x133830be8  'B' xvalue`.
Let C2 be `ExprWithCleanups 0x133830658  'const A' lvalue`

for each lifetime extended `MaterializeTemporaryExpr`
1. Handling M2, `CGF.pushLifetimeExtendedDestroy ` push a EHCleanup into 
`EHStack` and push a NormalCleanup into `LifetimeExtendedCleanupStack`.
2. Handling C2, pop out the cleanup in `EHStack` and then push the copy of 
cleanup which in `LifetimeExtendedCleanupStack` into `EHStack`, and resize 
`LifetimeExtendedCleanupStack` to old size(0).
3. Handling M1, `CGF.pushLifetimeExtendedDestroy ` push a EHCleanup into 
`EHStack` and push a NormalCleanup into `LifetimeExtendedCleanupStack`, now 
`EHStack` has 2 cleanups(~B(), ~A()) and `LifetimeExtendedCleanupStack` has 1 
cleanup(~B()).
4. Handling C1, pop out the top cleanup in `EHStack`, then emit the 2nd 
cleanup(emit call of ~A() in a `entry` BB), finally, push the copy of 
cleanup(~B()) which in `LifetimeExtendedCleanupStack` into `EHStack`, and 
resize `LifetimeExtendedCleanupStack` to old size(0).
5. Back to EmitCXXForRangeStmt, there are 1 cleanup(~B()) in `EHStack`, then 
`ForScope.ForceCleanup()` will emit this cleanup(call of ~B() in BB 
`for.cleanup`).

After the above steps, even if the lifetime of A is bound to `__range`, it is 
still not emit the expected cleanup.


```
`-CXXForRangeStmt 0x1338326d0 
  |-<<>>
  |-DeclStmt 0x133830d50 
  | `-VarDecl 0x133830940  col:19 implicit used __range1 'B 
&&' cinit
  |   `-ExprWithCleanups 0x133830be8  'B' xvalue
  | `-MaterializeTemporaryExpr 0x133830b80  'B' xvalue 
extended by Var 0x133830940 '__range1' 'B &&'
  |   `-CXXFunctionalCastExpr 0x1338307e0  'B' 
functional cast to B 
  | `-InitListExpr 0x133830408  'B'
  |   |-IntegerLiteral 0x133829da0  'int' 0
  |   `-CXXDefaultInitExpr 0x133830670  'const A' lvalue 
has rewritten init
  | `-ExprWithCleanups 0x133830658  'const 
A' lvalue
  |   `-MaterializeTemporaryExpr 0x1338305f0  
'const A' lvalue extended by Var 0x133830940 '__range1' 'B &&'
  | `-ImplicitCastExpr 0x1338305d8  'const 
A' 
  |   `-CXXFunctionalCastExpr 0x1338305b0  
'A' functional cast to A 
  | `-CXXBindTemporaryExpr 0x133830590  
'A' (CXXTemporary 0x133830590)
  |   `-InitListExpr 0x1338304f8  'A'
  | `-InitListExpr 0x133830540  
'int[1]'
  |   `-IntegerLiteral 0x1338297e8  'int' 0
```

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-09 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

The AST in the `B{A()}` case looks like the following.  If your patch changes 
the AST for `B{}` to look the same, it should be fine, I think?  From your 
description, I'm not exactly sure what's different about what 
CXXDefaultInitExpr rewriting generates.

```
  | `-VarDecl 0xc4927c0  col:113 implicit used __range1 
'B &&' cinit
  |   `-ExprWithCleanups 0xc492aa8  'B' xvalue
  | `-MaterializeTemporaryExpr 0xc492a00  'B' xvalue 
extended by Var 0xc4927c0 '__range1' 'B &&'
  |   `-CXXFunctionalCastExpr 0xc492678  'B' 
functional cast to B 
  | `-InitListExpr 0xc492508  'B'
  |   `-MaterializeTemporaryExpr 0xc492568  
'const A' lvalue extended by Var 0xc4927c0 '__range1' 'B &&'
  | `-ImplicitCastExpr 0xc492550  'const A' 

  |   `-CXXBindTemporaryExpr 0xc4718c8  'A' 
(CXXTemporary 0xc4718c8)
  | `-CXXTemporaryObjectExpr 0xc471890  
'A' 'void ()'
```

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-09 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

In `InitListChecker::FillInEmptyInitForField`, we will create a 
`CXXDefaultInitExpr` and fill in empty field `const A a& = A{};` for `for (auto 
& : B{}) {}` . Also there will have a `ExprWithCleanup` in 
`CXXDefaultInitExpr`. 
This is what I know about the difference in AST between the two cases, when I 
change the ExtendingDecl of `MaterializedTemporaryExpr`, it does not generate 
correct cleanups in CodeGen.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-08 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

`for (auto & : B{A()}) {}` currently works correctly, as far as I know (where 
B is a class with a member of type `const A&`).  And if I'm understanding 
correctly, `for (auto & : B{}) {}` is supposed to be semantically equivalent. 
 If the AST is significantly different, you should be addressing that in Sema, 
I think.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits

https://github.com/yronglin converted_to_draft 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits

yronglin wrote:

This PR does so many things that I will split it into multiple smaller PRs to 
make it easier to review.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

Thanks for your review! [P2718R0](https://wg21.link/P2718R0) introduce lifetime 
extensions in for-range loops. Basic support for P2718R0 has been implemented 
in https://github.com/llvm/llvm-project/pull/76361 and everything works fine. 
When I works on this PR, I found that the lifetime of temporaries 
in`CXXDefaultInitExpr` was not extended, even if `MaterializedTemporaryExpr` 
sets ExtendingDecl and bound to `__range` variable.  So I thought about my 
current approach and I'm not sure if this is the correct approach. Can you 
provide a direction for improvement? Should we modify the AST instead of 
handling it in CodeGen?

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits


@@ -311,9 +311,9 @@ pushTemporaryCleanup(CodeGenFunction , 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) &&

yronglin wrote:

I've revert this change.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-07 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From e5f2bfb1652118be0112b8242263942063b75b89 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Tue, 2 Apr 2024 23:47:33 +0800
Subject: [PATCH 1/2] [Clang] Extend lifetime of temporaries in
 mem-default-init for P2718R0

Signed-off-by: yronglin 
---
 clang/include/clang/Sema/Sema.h   |  47 
 clang/lib/CodeGen/CGExpr.cpp  |  62 +-
 clang/lib/CodeGen/CGStmt.cpp  |  15 +++
 clang/lib/CodeGen/CodeGenFunction.h   |  31 +
 clang/lib/Parse/ParseDecl.cpp |   4 -
 clang/lib/Sema/SemaExpr.cpp   |  11 +-
 clang/lib/Sema/SemaExprCXX.cpp|   2 +-
 clang/lib/Sema/SemaInit.cpp   |  36 +++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   1 -
 clang/lib/Sema/TreeTransform.h|   4 -
 clang/test/CXX/drs/dr16xx.cpp |   3 +-
 clang/test/CXX/drs/dr18xx.cpp |   7 +-
 clang/test/CXX/special/class.temporary/p6.cpp | 106 ++
 clang/test/SemaCXX/constexpr-default-arg.cpp  |   4 +-
 clang/test/SemaCXX/eval-crashes.cpp   |   6 +-
 15 files changed, 222 insertions(+), 117 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f49bc724c96c89..0a07e850c74e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5078,34 +5078,6 @@ class Sema final : public SemaBase {
 /// example, in a for-range initializer).
 bool InLifetimeExtendingContext = false;
 
-/// Whether we are currently in a context in which all temporaries must be
-/// materialized.
-///
-/// [class.temporary]/p2:
-/// The materialization of a temporary object is generally delayed as long
-/// as possible in order to avoid creating unnecessary temporary objects.
-///
-/// Temporary objects are materialized:
-///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-///   [expr.const.cast], [expr.cast]),
-///
-///   (2.2) when performing member access on a class prvalue ([expr.ref],
-///   [expr.mptr.oper]),
-///
-///   (2.3) when performing an array-to-pointer conversion or subscripting
-///   on an array prvalue ([conv.array], [expr.sub]),
-///
-///   (2.4) when initializing an object of type
-///   std​::​initializer_list from a braced-init-list
-///   ([dcl.init.list]),
-///
-///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-///
-///   (2.6) when a prvalue that has type other than cv void appears as a
-///   discarded-value expression ([expr.context]).
-bool InMaterializeTemporaryObjectContext = false;
-
 // When evaluating immediate functions in the initializer of a default
 // argument or default member initializer, this is the declaration whose
 // default initializer is being evaluated and the location of the call
@@ -6386,19 +6358,6 @@ class Sema final : public SemaBase {
 }
   }
 
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-if (ExprEvalContexts.size() > 2 &&
-ExprEvalContexts[ExprEvalContexts.size() - 2]
-.InMaterializeTemporaryObjectContext) {
-  auto  = ExprEvalContexts.back();
-  auto  = ExprEvalContexts[ExprEvalContexts.size() - 2];
-  LastRecord.InMaterializeTemporaryObjectContext =
-  PrevRecord.InMaterializeTemporaryObjectContext;
-}
-  }
-
   DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
 return getDefaultedFunctionKind(FD).asComparison();
   }
@@ -6542,12 +6501,6 @@ class Sema final : public SemaBase {
   /// used in initializer of the field.
   llvm::MapVector DeleteExprs;
 
-  bool isInMaterializeTemporaryObjectContext() const {
-assert(!ExprEvalContexts.empty() &&
-   "Must be in an expression evaluation context");
-return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
-  }
-
   ParsedType getInheritingConstructorName(CXXScopeSpec ,
   SourceLocation NameLoc,
   IdentifierInfo );
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 2480972f1432f7..27f616d497a2c5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -274,9 +274,9 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
   llvm_unreachable("bad evaluation kind");
 }
 
-static void
-pushTemporaryCleanup(CodeGenFunction , const MaterializeTemporaryExpr *M,
- const Expr *E, Address ReferenceTemporary) {
+void CodeGenFunction::pushTemporaryCleanup(const MaterializeTemporaryExpr *M,
+

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread Eli Friedman via cfe-commits


@@ -311,9 +311,9 @@ pushTemporaryCleanup(CodeGenFunction , 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) &&

efriedma-quic wrote:

Mixing together a bunch of cleanups with your actual changes makes things hard 
to read.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread Eli Friedman via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

efriedma-quic wrote:

What makes temporaries in for-range statements different from other 
temporaries?  The standard explicitly defines for-range in terms of a regular 
for-loop; it shouldn't require any special handling unless our AST is somehow 
deficient.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread Vlad Serebrennikov via cfe-commits

https://github.com/Endilll commented:

`Sema.h` changes look good.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)
+ForScope.setForRangeVar(RangeVar);
 
   // Evaluate the first pieces before the loop.
   if (S.getInit())
 EmitStmt(S.getInit());
   EmitStmt(S.getRangeStmt());
+
+  // Emit cleanup for tempories in for-range-init expression.
+  if (getLangOpts().CPlusPlus23) {

yronglin wrote:

Same as above.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits


@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt ,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast(S.getRangeStmt());
+  const VarDecl *RangeVar = cast(RangeDS->getSingleDecl());
+  if (getLangOpts().CPlusPlus23)

yronglin wrote:

I think we need to continue to improve here. We can decide whether to extend 
the lifetime in Sema. For example: do not store temporaries into 
ExpressionEvaluationContext::ForRangeLifetimeExtendTemps when building 
for-range-init expressions.

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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From e5f2bfb1652118be0112b8242263942063b75b89 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/include/clang/Sema/Sema.h   |  47 
 clang/lib/CodeGen/CGExpr.cpp  |  62 +-
 clang/lib/CodeGen/CGStmt.cpp  |  15 +++
 clang/lib/CodeGen/CodeGenFunction.h   |  31 +
 clang/lib/Parse/ParseDecl.cpp |   4 -
 clang/lib/Sema/SemaExpr.cpp   |  11 +-
 clang/lib/Sema/SemaExprCXX.cpp|   2 +-
 clang/lib/Sema/SemaInit.cpp   |  36 +++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   1 -
 clang/lib/Sema/TreeTransform.h|   4 -
 clang/test/CXX/drs/dr16xx.cpp |   3 +-
 clang/test/CXX/drs/dr18xx.cpp |   7 +-
 clang/test/CXX/special/class.temporary/p6.cpp | 106 ++
 clang/test/SemaCXX/constexpr-default-arg.cpp  |   4 +-
 clang/test/SemaCXX/eval-crashes.cpp   |   6 +-
 15 files changed, 222 insertions(+), 117 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f49bc724c96c89..0a07e850c74e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5078,34 +5078,6 @@ class Sema final : public SemaBase {
 /// example, in a for-range initializer).
 bool InLifetimeExtendingContext = false;
 
-/// Whether we are currently in a context in which all temporaries must be
-/// materialized.
-///
-/// [class.temporary]/p2:
-/// The materialization of a temporary object is generally delayed as long
-/// as possible in order to avoid creating unnecessary temporary objects.
-///
-/// Temporary objects are materialized:
-///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-///   [expr.const.cast], [expr.cast]),
-///
-///   (2.2) when performing member access on a class prvalue ([expr.ref],
-///   [expr.mptr.oper]),
-///
-///   (2.3) when performing an array-to-pointer conversion or subscripting
-///   on an array prvalue ([conv.array], [expr.sub]),
-///
-///   (2.4) when initializing an object of type
-///   std​::​initializer_list from a braced-init-list
-///   ([dcl.init.list]),
-///
-///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-///
-///   (2.6) when a prvalue that has type other than cv void appears as a
-///   discarded-value expression ([expr.context]).
-bool InMaterializeTemporaryObjectContext = false;
-
 // When evaluating immediate functions in the initializer of a default
 // argument or default member initializer, this is the declaration whose
 // default initializer is being evaluated and the location of the call
@@ -6386,19 +6358,6 @@ class Sema final : public SemaBase {
 }
   }
 
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-if (ExprEvalContexts.size() > 2 &&
-ExprEvalContexts[ExprEvalContexts.size() - 2]
-.InMaterializeTemporaryObjectContext) {
-  auto  = ExprEvalContexts.back();
-  auto  = ExprEvalContexts[ExprEvalContexts.size() - 2];
-  LastRecord.InMaterializeTemporaryObjectContext =
-  PrevRecord.InMaterializeTemporaryObjectContext;
-}
-  }
-
   DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
 return getDefaultedFunctionKind(FD).asComparison();
   }
@@ -6542,12 +6501,6 @@ class Sema final : public SemaBase {
   /// used in initializer of the field.
   llvm::MapVector DeleteExprs;
 
-  bool isInMaterializeTemporaryObjectContext() const {
-assert(!ExprEvalContexts.empty() &&
-   "Must be in an expression evaluation context");
-return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
-  }
-
   ParsedType getInheritingConstructorName(CXXScopeSpec ,
   SourceLocation NameLoc,
   IdentifierInfo );
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 2480972f1432f7..27f616d497a2c5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -274,9 +274,9 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
   llvm_unreachable("bad evaluation kind");
 }
 
-static void
-pushTemporaryCleanup(CodeGenFunction , const MaterializeTemporaryExpr *M,
- const Expr *E, Address ReferenceTemporary) {
+void CodeGenFunction::pushTemporaryCleanup(const MaterializeTemporaryExpr *M,
+

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (yronglin)


Changes

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 
confirmation in https://github.com/llvm/llvm-project/issues/85613, we should 
extend lifetime for that.

There are two main modifications made to this PR:
- Extend lifetime of temporaries in `CXXDefaultInitExpr`. This reuse 
`CXXDefaultInitExpr` rewrite machinery.
- Before emitting the `__range` variable, we store the `__range` variable decl 
in `LexicalScope`. During emitting the `__range` variable, if we encounter a 
`MaterializedTemporaryExpr` whose lifetime is extended by the `__range` 
variable, we collect these temporaries and store into 
`LexicalScope::ForRangeInitTemps`. Once `__range` variable emitting finished, 
we will emitting the cleanups for the temporaries which we collected. 

TODO: The lit test not add yet, because I'm not sure it's the correct approach, 
but I've posted some cases in https://github.com/llvm/llvm-project/issues/85613.


---

Patch is 27.12 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/86960.diff


15 Files Affected:

- (modified) clang/include/clang/Sema/Sema.h (-47) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+33-29) 
- (modified) clang/lib/CodeGen/CGStmt.cpp (+18) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+31) 
- (modified) clang/lib/Parse/ParseDecl.cpp (-4) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+6-5) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaInit.cpp (+23-13) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (-1) 
- (modified) clang/lib/Sema/TreeTransform.h (-4) 
- (modified) clang/test/CXX/drs/dr16xx.cpp (+1-2) 
- (modified) clang/test/CXX/drs/dr18xx.cpp (+2-5) 
- (modified) clang/test/CXX/special/class.temporary/p6.cpp (+106) 
- (modified) clang/test/SemaCXX/constexpr-default-arg.cpp (+2-2) 
- (modified) clang/test/SemaCXX/eval-crashes.cpp (+2-4) 


``diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f49bc724c96c89..0a07e850c74e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5078,34 +5078,6 @@ class Sema final : public SemaBase {
 /// example, in a for-range initializer).
 bool InLifetimeExtendingContext = false;
 
-/// Whether we are currently in a context in which all temporaries must be
-/// materialized.
-///
-/// [class.temporary]/p2:
-/// The materialization of a temporary object is generally delayed as long
-/// as possible in order to avoid creating unnecessary temporary objects.
-///
-/// Temporary objects are materialized:
-///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-///   [expr.const.cast], [expr.cast]),
-///
-///   (2.2) when performing member access on a class prvalue ([expr.ref],
-///   [expr.mptr.oper]),
-///
-///   (2.3) when performing an array-to-pointer conversion or subscripting
-///   on an array prvalue ([conv.array], [expr.sub]),
-///
-///   (2.4) when initializing an object of type
-///   std​::​initializer_list from a braced-init-list
-///   ([dcl.init.list]),
-///
-///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-///
-///   (2.6) when a prvalue that has type other than cv void appears as a
-///   discarded-value expression ([expr.context]).
-bool InMaterializeTemporaryObjectContext = false;
-
 // When evaluating immediate functions in the initializer of a default
 // argument or default member initializer, this is the declaration whose
 // default initializer is being evaluated and the location of the call
@@ -6386,19 +6358,6 @@ class Sema final : public SemaBase {
 }
   }
 
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-if (ExprEvalContexts.size() > 2 &&
-ExprEvalContexts[ExprEvalContexts.size() - 2]
-.InMaterializeTemporaryObjectContext) {
-  auto  = ExprEvalContexts.back();
-  auto  = ExprEvalContexts[ExprEvalContexts.size() - 2];
-  LastRecord.InMaterializeTemporaryObjectContext =
-  PrevRecord.InMaterializeTemporaryObjectContext;
-}
-  }
-
   DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
 return getDefaultedFunctionKind(FD).asComparison();
   }
@@ -6542,12 +6501,6 @@ class Sema final : public SemaBase {
   /// used in initializer of the field.
   llvm::MapVector DeleteExprs;
 
-  bool isInMaterializeTemporaryObjectContext() const {
-assert(!ExprEvalContexts.empty() &&
-   

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-codegen

Author: None (yronglin)


Changes

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 
confirmation in https://github.com/llvm/llvm-project/issues/85613, we should 
extend lifetime for that.

There are two main modifications made to this PR:
- Extend lifetime of temporaries in `CXXDefaultInitExpr`. This reuse 
`CXXDefaultInitExpr` rewrite machinery.
- Before emitting the `__range` variable, we store the `__range` variable decl 
in `LexicalScope`. During emitting the `__range` variable, if we encounter a 
`MaterializedTemporaryExpr` whose lifetime is extended by the `__range` 
variable, we collect these temporaries and store into 
`LexicalScope::ForRangeInitTemps`. Once `__range` variable emitting finished, 
we will emitting the cleanups for the temporaries which we collected. 

TODO: The lit test not add yet, because I'm not sure it's the correct approach, 
but I've posted some cases in https://github.com/llvm/llvm-project/issues/85613.


---

Patch is 27.12 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/86960.diff


15 Files Affected:

- (modified) clang/include/clang/Sema/Sema.h (-47) 
- (modified) clang/lib/CodeGen/CGExpr.cpp (+33-29) 
- (modified) clang/lib/CodeGen/CGStmt.cpp (+18) 
- (modified) clang/lib/CodeGen/CodeGenFunction.h (+31) 
- (modified) clang/lib/Parse/ParseDecl.cpp (-4) 
- (modified) clang/lib/Sema/SemaExpr.cpp (+6-5) 
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+1-1) 
- (modified) clang/lib/Sema/SemaInit.cpp (+23-13) 
- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (-1) 
- (modified) clang/lib/Sema/TreeTransform.h (-4) 
- (modified) clang/test/CXX/drs/dr16xx.cpp (+1-2) 
- (modified) clang/test/CXX/drs/dr18xx.cpp (+2-5) 
- (modified) clang/test/CXX/special/class.temporary/p6.cpp (+106) 
- (modified) clang/test/SemaCXX/constexpr-default-arg.cpp (+2-2) 
- (modified) clang/test/SemaCXX/eval-crashes.cpp (+2-4) 


``diff
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f49bc724c96c89..0a07e850c74e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5078,34 +5078,6 @@ class Sema final : public SemaBase {
 /// example, in a for-range initializer).
 bool InLifetimeExtendingContext = false;
 
-/// Whether we are currently in a context in which all temporaries must be
-/// materialized.
-///
-/// [class.temporary]/p2:
-/// The materialization of a temporary object is generally delayed as long
-/// as possible in order to avoid creating unnecessary temporary objects.
-///
-/// Temporary objects are materialized:
-///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-///   [expr.const.cast], [expr.cast]),
-///
-///   (2.2) when performing member access on a class prvalue ([expr.ref],
-///   [expr.mptr.oper]),
-///
-///   (2.3) when performing an array-to-pointer conversion or subscripting
-///   on an array prvalue ([conv.array], [expr.sub]),
-///
-///   (2.4) when initializing an object of type
-///   std​::​initializer_list from a braced-init-list
-///   ([dcl.init.list]),
-///
-///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-///
-///   (2.6) when a prvalue that has type other than cv void appears as a
-///   discarded-value expression ([expr.context]).
-bool InMaterializeTemporaryObjectContext = false;
-
 // When evaluating immediate functions in the initializer of a default
 // argument or default member initializer, this is the declaration whose
 // default initializer is being evaluated and the location of the call
@@ -6386,19 +6358,6 @@ class Sema final : public SemaBase {
 }
   }
 
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-if (ExprEvalContexts.size() > 2 &&
-ExprEvalContexts[ExprEvalContexts.size() - 2]
-.InMaterializeTemporaryObjectContext) {
-  auto  = ExprEvalContexts.back();
-  auto  = ExprEvalContexts[ExprEvalContexts.size() - 2];
-  LastRecord.InMaterializeTemporaryObjectContext =
-  PrevRecord.InMaterializeTemporaryObjectContext;
-}
-  }
-
   DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
 return getDefaultedFunctionKind(FD).asComparison();
   }
@@ -6542,12 +6501,6 @@ class Sema final : public SemaBase {
   /// used in initializer of the field.
   llvm::MapVector DeleteExprs;
 
-  bool isInMaterializeTemporaryObjectContext() const {
-assert(!ExprEvalContexts.empty() &&
- 

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin ready_for_review 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-06 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From 55f6fe094d50759784fdf7ba2e80616bc7bf3f4b 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/include/clang/Sema/Sema.h   |  47 
 clang/lib/CodeGen/CGExpr.cpp  |  62 +-
 clang/lib/CodeGen/CGStmt.cpp  |  18 +++
 clang/lib/CodeGen/CodeGenFunction.h   |  31 +
 clang/lib/Parse/ParseDecl.cpp |   4 -
 clang/lib/Sema/SemaExpr.cpp   |  11 +-
 clang/lib/Sema/SemaExprCXX.cpp|   2 +-
 clang/lib/Sema/SemaInit.cpp   |  36 +++---
 .../lib/Sema/SemaTemplateInstantiateDecl.cpp  |   1 -
 clang/lib/Sema/TreeTransform.h|   4 -
 clang/test/CXX/drs/dr16xx.cpp |   3 +-
 clang/test/CXX/drs/dr18xx.cpp |   7 +-
 clang/test/CXX/special/class.temporary/p6.cpp | 106 ++
 clang/test/SemaCXX/constexpr-default-arg.cpp  |   4 +-
 clang/test/SemaCXX/eval-crashes.cpp   |   6 +-
 15 files changed, 225 insertions(+), 117 deletions(-)

diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index f49bc724c96c89..0a07e850c74e47 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5078,34 +5078,6 @@ class Sema final : public SemaBase {
 /// example, in a for-range initializer).
 bool InLifetimeExtendingContext = false;
 
-/// Whether we are currently in a context in which all temporaries must be
-/// materialized.
-///
-/// [class.temporary]/p2:
-/// The materialization of a temporary object is generally delayed as long
-/// as possible in order to avoid creating unnecessary temporary objects.
-///
-/// Temporary objects are materialized:
-///   (2.1) when binding a reference to a prvalue ([dcl.init.ref],
-///   [expr.type.conv], [expr.dynamic.cast], [expr.static.cast],
-///   [expr.const.cast], [expr.cast]),
-///
-///   (2.2) when performing member access on a class prvalue ([expr.ref],
-///   [expr.mptr.oper]),
-///
-///   (2.3) when performing an array-to-pointer conversion or subscripting
-///   on an array prvalue ([conv.array], [expr.sub]),
-///
-///   (2.4) when initializing an object of type
-///   std​::​initializer_list from a braced-init-list
-///   ([dcl.init.list]),
-///
-///   (2.5) for certain unevaluated operands ([expr.typeid], [expr.sizeof])
-///
-///   (2.6) when a prvalue that has type other than cv void appears as a
-///   discarded-value expression ([expr.context]).
-bool InMaterializeTemporaryObjectContext = false;
-
 // When evaluating immediate functions in the initializer of a default
 // argument or default member initializer, this is the declaration whose
 // default initializer is being evaluated and the location of the call
@@ -6386,19 +6358,6 @@ class Sema final : public SemaBase {
 }
   }
 
-  /// keepInMaterializeTemporaryObjectContext - Pull down
-  /// InMaterializeTemporaryObjectContext flag from previous context.
-  void keepInMaterializeTemporaryObjectContext() {
-if (ExprEvalContexts.size() > 2 &&
-ExprEvalContexts[ExprEvalContexts.size() - 2]
-.InMaterializeTemporaryObjectContext) {
-  auto  = ExprEvalContexts.back();
-  auto  = ExprEvalContexts[ExprEvalContexts.size() - 2];
-  LastRecord.InMaterializeTemporaryObjectContext =
-  PrevRecord.InMaterializeTemporaryObjectContext;
-}
-  }
-
   DefaultedComparisonKind getDefaultedComparisonKind(const FunctionDecl *FD) {
 return getDefaultedFunctionKind(FD).asComparison();
   }
@@ -6542,12 +6501,6 @@ class Sema final : public SemaBase {
   /// used in initializer of the field.
   llvm::MapVector DeleteExprs;
 
-  bool isInMaterializeTemporaryObjectContext() const {
-assert(!ExprEvalContexts.empty() &&
-   "Must be in an expression evaluation context");
-return ExprEvalContexts.back().InMaterializeTemporaryObjectContext;
-  }
-
   ParsedType getInheritingConstructorName(CXXScopeSpec ,
   SourceLocation NameLoc,
   IdentifierInfo );
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 2480972f1432f7..27f616d497a2c5 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -274,9 +274,9 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E,
   llvm_unreachable("bad evaluation kind");
 }
 
-static void
-pushTemporaryCleanup(CodeGenFunction , const MaterializeTemporaryExpr *M,
- const Expr *E, Address ReferenceTemporary) {
+void CodeGenFunction::pushTemporaryCleanup(const MaterializeTemporaryExpr *M,
+

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From 297e4f6b4303d1847f2cbddb6d00aaccbaeb2600 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| 62 +++--
 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, 86 insertions(+), 35 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 54432353e7420d..5cd66c43ea88dc 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 , 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 , 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 ? ::destroyARCStrongPrecise
 : ::destroyARCStrongImprecise;
 } else {
@@ -317,13 +317,12 @@ pushTemporaryCleanup(CodeGenFunction , const 
MaterializeTemporaryExpr *M,
   Destroy = ::destroyARCWeak;
 }
 if (Duration == SD_FullExpression)
-  CGF.pushDestroy(CleanupKind, ReferenceTemporary,
-  M->getType(), *Destroy,
-  CleanupKind & EHCleanup);
+  pushDestroy(CleanupKind, ReferenceTemporary, M->getType(), *Destroy,
+  CleanupKind & EHCleanup);
 else
-  CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
-  M->getType(),
-  *Destroy, CleanupKind & EHCleanup);
+  pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
+  M->getType(), *Destroy,
+  CleanupKind & EHCleanup);
 return;
 
   case SD_Dynamic:
@@ -352,32 +351,31 @@ pushTemporaryCleanup(CodeGenFunction , const 
MaterializeTemporaryExpr *M,
 llvm::FunctionCallee CleanupFn;
 llvm::Constant *CleanupArg;
 if (E->getType()->isArrayType()) {
-  CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper(
-  ReferenceTemporary, E->getType(),
-  CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions,
+  CleanupFn = CodeGenFunction(CGM).generateDestroyHelper(
+  ReferenceTemporary, E->getType(), 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(),
-CodeGenFunction::destroyCXXObject,
-CGF.getLangOpts().Exceptions);
+pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(),
+CodeGenFunction::destroyCXXObject, getLangOpts().Exceptions);
 break;
 
   case SD_Automatic:
-CGF.pushLifetimeExtendedDestroy(NormalAndEHCleanup,
-ReferenceTemporary, E->getType(),
-

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin edited 
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] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From 8bd2742f6bccc0ec7229950e901e99717ba9acb3 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| 62 +++--
 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, 86 insertions(+), 35 deletions(-)

diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 54432353e7420d..5cd66c43ea88dc 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 , 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 , 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 ? ::destroyARCStrongPrecise
 : ::destroyARCStrongImprecise;
 } else {
@@ -317,13 +317,12 @@ pushTemporaryCleanup(CodeGenFunction , const 
MaterializeTemporaryExpr *M,
   Destroy = ::destroyARCWeak;
 }
 if (Duration == SD_FullExpression)
-  CGF.pushDestroy(CleanupKind, ReferenceTemporary,
-  M->getType(), *Destroy,
-  CleanupKind & EHCleanup);
+  pushDestroy(CleanupKind, ReferenceTemporary, M->getType(), *Destroy,
+  CleanupKind & EHCleanup);
 else
-  CGF.pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
-  M->getType(),
-  *Destroy, CleanupKind & EHCleanup);
+  pushLifetimeExtendedDestroy(CleanupKind, ReferenceTemporary,
+  M->getType(), *Destroy,
+  CleanupKind & EHCleanup);
 return;
 
   case SD_Dynamic:
@@ -352,32 +351,31 @@ pushTemporaryCleanup(CodeGenFunction , const 
MaterializeTemporaryExpr *M,
 llvm::FunctionCallee CleanupFn;
 llvm::Constant *CleanupArg;
 if (E->getType()->isArrayType()) {
-  CleanupFn = CodeGenFunction(CGF.CGM).generateDestroyHelper(
-  ReferenceTemporary, E->getType(),
-  CodeGenFunction::destroyCXXObject, CGF.getLangOpts().Exceptions,
+  CleanupFn = CodeGenFunction(CGM).generateDestroyHelper(
+  ReferenceTemporary, E->getType(), 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(),
-CodeGenFunction::destroyCXXObject,
-CGF.getLangOpts().Exceptions);
+pushDestroy(NormalAndEHCleanup, ReferenceTemporary, E->getType(),
+CodeGenFunction::destroyCXXObject, getLangOpts().Exceptions);
 break;
 
   case SD_Automatic:
-CGF.pushLifetimeExtendedDestroy(NormalAndEHCleanup,
-ReferenceTemporary, E->getType(),
-

[clang] [Clang] Extend lifetime of temporaries in mem-default-init for P2718R0 (PR #86960)

2024-04-02 Thread via cfe-commits

https://github.com/yronglin edited 
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