The assertion doesn't hold if there are temporaries created in the AsmStmt passed to the method.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
ping
I think the assertion is assuming StmtExpr is created only for GNU statement expressions, but it's created for asm statements too (see https://github.com/llvm/llvm-project/commit/3050d9bdb84e322e122219d54aedfe2d8ef7c51c).
The assertion was assuming "the expression doesn't need cleanups", have you considered adding a test that checks that the destructor of the temporary inside the asm statement is called, to ensure these temporaries are properly handled?
Add a codegen test that checks destructors for temporaries inside asm statements are called.
clang/test/CodeGenCXX/asm.cpp | ||
---|---|---|
22 | Please add another statement here after the asm statement to check that the destructor is called at the end of the asm statement, not at the }. |
clang/lib/Sema/SemaExpr.cpp | ||
---|---|---|
15772–15773 | Is it possible to pass a flag into here to indicate if we're really building an asm statement? I don't think we want to remove the assert for a user-written statement expression that happens to begin with an asm statement. It's ironic that we're building a statement expression to wrap an asm statement in order to make sure that cleanups are handled properly, and the StmtExpr is asserting because it doesn't expect to need to handle cleanups... |
clang/lib/Sema/SemaExpr.cpp | ||
---|---|---|
15772–15773 | Maybe we can add a flag to StmtExpr and set it in Sema::MaybeCreateStmtWithCleanups to distinguish StmtExprs that are created for gnu statement expressions from those that aren't? If we don't want to use StmtExpr for asm statements, maybe we have to create a new Stmt type just for that purpose as suggested in Sema::MaybeCreateStmtWithCleanups. |
The cleanups arise from expressions in the constraints, right? There are a number of places where ExprWithCleanups does not mean the cleanups are independently nested within that expression; it's notably not how it works ever for something as basic as a variable initializer. If we want the lifetime of temporaries in asm operands to include the full duration of the asm statement, I think we can just declare by fiat that that's how it works for AsmStmt instead of unnaturally wrapping things this way.
Or do we have a problem where the semantics are different for different kinds of asm statements?
No, I don't think there are any problems. We can probably just pop the cleanups at the end of the asm statement.
The original commit message said the asm calls had to be wrapped in StmtExprs because temporaries would get destroyed before the asm calls, but that doesn't seem to happen anymore. It looks like they'd be destroyed at the end of the enclosing scope instead.
Yeah, I think the appropriate thing is to just treat the entire asm statement like it's a single full-expression. As always, that implies an annoying lifetime for blocks and C compound literals.
Stop wrapping a GCCAsmStmt with an ExprWithCleanups. Instead, just pop the cleanups after the asm statement to destruct the temporaries.
I've removed the call to ActOnFinishFullStmt in CoroutineStmtBuilder::makeOnFallthrough too. BuildCoreturnStmt calls ActOnFinishFullExpr, so I don't think it's necessary to call ActOnFinishFullStmt after that.
The change to SemaCoroutine.cpp might be good. But I feel like it is irreverent to the revision. If you want, could you please do the change in another revision?
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
2291 ↗ | (On Diff #437566) | Do we need to do anything special when entering the full expressions to make sure that enclosing-block features like blocks and C compound literals have the right lifetime? |
Fix misleading comment and add a test case for C compound literal.
clang/lib/CodeGen/CGStmt.cpp | ||
---|---|---|
2291 ↗ | (On Diff #437566) | I don't think there is anything special we have to do here. The cleanups for both blocks and C compound literals are pushed by calling pushLifetimeExtendedDestroy so that their lifetime is extended till the end of the enclosing scope. |
Is it possible to pass a flag into here to indicate if we're really building an asm statement? I don't think we want to remove the assert for a user-written statement expression that happens to begin with an asm statement.
It's ironic that we're building a statement expression to wrap an asm statement in order to make sure that cleanups are handled properly, and the StmtExpr is asserting because it doesn't expect to need to handle cleanups...