[cfe-dev] How to force temporary cleanup without ExprWithCleanups?

Xun Li via cfe-dev cfe-dev at lists.llvm.org
Wed Nov 4 13:23:41 PST 2020


Hi,

I am working on fixing a bug related to coroutines.
A "co_await <expr>" expression in C++ is typically transformed into
AST like this (largely simplified for demonstration purpose):

-ExprWithCleanups
    `-CoawaitExpr
        |-MaterializeTemporaryExpr  ...  'Awaiter'
        |    `- ...
        |-CallExpr
        |        ...
        |            `--MemberExpr  ...  .await_suspend
        |                ...
        |                    `-MaterializeTemporaryExpr
        |                        ...
        |-...

CoawaitExpr contains many subexprs, among them worth mentioning is: an
Awaiter object (MaterializeTemporaryExpr) used by all other subexprs;
and a "Suspend" subexpr that attempts to suspend the current coroutine
and resume another one. That Suspend subexpr may also creates new
MaterializeTemporaryExpr within it.

Now, all the materialized temporaries in this entire expression are
cleaned up together by the ExprWithCleanups at the top. This is
causing problems: some of the temporaries should have effectively died
right away after being used, however their destructor call is delayed
until after the coroutine suspension. This is fine in normal
functions. Unfortunately, for coroutines, the coroutine frame may have
been destroyed after a suspension, and we can no longer call those
destructors as their object source has died. So I need a way to
cleanup all temp objects created and died before the coroutine
suspension.

I tried to insert extra ExprWithCleanups into the subexprs, for
example, wrapping each subexpr with an ExprWithCleanups. But it seems
like I cannot use it that way. When I did it, it somehow made the
original wrapping ExprWithCleanups disappear and leaving the Awaiter
object cleaned up in a weird place.

What's the best way to fix this? Any suggestions would be much
appreciated! Thanks!
-- 
Xun


More information about the cfe-dev mailing list