[Bug c++/95599] [coroutines] destructor for temporary operand to co_yield expression called before end of full-expression

cvs-commit at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Jul 29 09:59:13 GMT 2020


--- Comment #7 from CVS Commits <cvs-commit at gcc dot gnu.org> ---
The releases/gcc-10 branch has been updated by Iain D Sandoe


commit r10-8545-gf43a1b1d1718969423337190ddbbbc9037c67783
Author: Iain Sandoe <iain@sandoe.co.uk>
Date:   Sun Jul 19 18:39:21 2020 +0100

    coroutines: Correct frame capture of compiler temps [PR95591+4].

    When a full expression contains a co_await (or co_yield), this means
    that it might be suspended; which would destroy temporary variables
    (on a stack for example).  However the language guarantees that such
    temporaries are live until the end of the expression.

    In order to preserve this, we 'promote' temporaries where necessary
    so that they are saved in the coroutine frame (which allows them to
    remain live potentially until the frame is destroyed).  In addition,
    sub-expressions that produce control flow (such as TRUTH_AND/OR_IF
    or COND_EXPR) must be handled specifically to ensure that await
    expressions are properly expanded.

    This patch corrects two mistakes in which we were (a) failing to
    promote some temporaries and (b) we we failing to sequence DTORs for
    the captures properly. This manifests in a number of related (but not
    exact duplicate) PRs.

    The revised code collects the actions into one place and maps all the
    control flow into one form - a benefit of this is that co_returns are
    now expanded earlier (which provides an opportunity to address PR95517
    in some future patch).

    We replace a statement that contains await expression(s) with a bind
    scope that has a variable list describing the temporaries that have
    been 'promoted' and a statement list that contains a series of cleanup
    expressions for each of those.  Where we encounter nested conditional
    expressions, these are wrapped in a try-finally block with a guard var
    for each sub-expression variable that needs a DTOR.  The guards are all
    declared and initialized to false before the first conditional sub-
    expression.  The 'finally' block contains a series of if blocks (one
    per guard variable) enclosing the relevant DTOR.

    Variables listed in a bind scope in this manner are automatically moved
    to a coroutine frame version by existing code (so we re-use that rather
    than having a separate mechanism).


            PR c++/95591
            PR c++/95599
            PR c++/95823
            PR c++/95824
            PR c++/95895
            * coroutines.cc (struct coro_ret_data): Delete.
            (coro_maybe_expand_co_return): Delete.
            (co_return_expander): Delete.
            (expand_co_returns): Delete.
            (co_await_find_in_subtree): Remove unused name.
            (build_actor_fn): Remove unused parm, remove handling
            for co_return expansion.
            (register_await_info): Demote duplicate info message to a
            (coro_make_frame_entry): Move closer to use site.
            (struct susp_frame_data): Add fields for final suspend label
            and a flag to indicate await expressions with initializers.
            (captures_temporary): Delete.
            (register_awaits): Remove unused code, update comments.
            (find_any_await): New.
            (tmp_target_expr_p): New.
            (struct interesting): New.
            (find_interesting_subtree): New.
            (struct var_nest_node): New.
            (flatten_await_stmt): New.
            (handle_nested_conditionals): New.
            (process_conditional): New.
            (replace_statement_captures): Rename to...
            (maybe_promote_temps): ... this.
            (maybe_promote_captured_temps): Delete.
            (analyze_expression_awaits): Check for await expressions with
            initializers.  Simplify handling for truth-and/or-if.
            (expand_one_truth_if): Simplify (map cases that need expansion
            to COND_EXPR).
            (await_statement_walker): Handle CO_RETURN_EXPR. Simplify the
            handling for truth-and/or-if expressions.
            (register_local_var_uses): Ensure that we create names in the
            implementation namespace.
            (morph_fn_to_coro): Add final suspend label to suspend frame
            callback data and remove it from the build_actor_fn call.


            PR c++/95591
            PR c++/95599
            PR c++/95823
            PR c++/95824
            PR c++/95895
            * g++.dg/coroutines/pr95591.C: New test.
            * g++.dg/coroutines/pr95599.C: New test.
            * g++.dg/coroutines/pr95823.C: New test.
            * g++.dg/coroutines/pr95824.C: New test.

    (cherry picked from commit 0f66b8486cea8668020e4bd48f261b760cb579be)

More information about the Gcc-bugs mailing list