================
@@ -1230,11 +1230,26 @@ CodeGenFunction::EmitCXXForRangeStmt(const 
CXXForRangeStmt &S,
   JumpDest LoopExit = getJumpDestInCurrentScope("for.end");
 
   LexicalScope ForScope(*this, S.getSourceRange());
+  const DeclStmt *RangeDS = cast<DeclStmt>(S.getRangeStmt());
+  const VarDecl *RangeVar = cast<VarDecl>(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 <col:19, col:22> 'B' xvalue 
extended by Var 0x133830940 '__range1' 'B &&'`
Let M2 be `MaterializeTemporaryExpr 0x1338305f0 <col:16, col:21> 'const A' 
lvalue extended by Var 0x133830940 '__range1' 'B &&'`
Let C1 be `ExprWithCleanups 0x133830be8 <col:19, col:22> 'B' xvalue`.
Let C2 be `ExprWithCleanups 0x133830658 <line:10:16, col:21> '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 <line:17:3, col:36>
      |-<<<NULL>>>
      |-DeclStmt 0x133830d50 <col:19>
      | `-VarDecl 0x133830940 <col:19, col:22> col:19 implicit used __range1 'B 
&&' cinit
      |   `-ExprWithCleanups 0x133830be8 <col:19, col:22> 'B' xvalue
      |     `-MaterializeTemporaryExpr 0x133830b80 <col:19, col:22> 'B' xvalue 
extended by Var 0x133830940 '__range1' 'B &&'
      |       `-CXXFunctionalCastExpr 0x1338307e0 <col:19, col:22> 'B' 
functional cast to B <NoOp>
      |         `-InitListExpr 0x133830408 <col:20, col:22> 'B'
      |           |-IntegerLiteral 0x133829da0 <col:21> 'int' 0
      |           `-CXXDefaultInitExpr 0x133830670 <col:22> 'const A' lvalue 
has rewritten init
      |             `-ExprWithCleanups 0x133830658 <line:10:16, col:21> 'const 
A' lvalue
      |               `-MaterializeTemporaryExpr 0x1338305f0 <col:16, col:21> 
'const A' lvalue extended by Var 0x133830940 '__range1' 'B &&'
      |                 `-ImplicitCastExpr 0x1338305d8 <col:16, col:21> 'const 
A' <NoOp>
      |                   `-CXXFunctionalCastExpr 0x1338305b0 <col:16, col:21> 
'A' functional cast to A <NoOp>
      |                     `-CXXBindTemporaryExpr 0x133830590 <col:17, col:21> 
'A' (CXXTemporary 0x133830590)
      |                       `-InitListExpr 0x1338304f8 <col:17, col:21> 'A'
      |                         `-InitListExpr 0x133830540 <col:18, col:20> 
'int[1]'
      |                           `-IntegerLiteral 0x1338297e8 <col:19> '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

Reply via email to