From: Iain Sandoe Date: Sat, 2 Oct 2021 12:40:09 +0000 (+0100) Subject: coroutines: Ensure co_await_exprs have TREE_SIDE_EFFECTS set [PR 101133]. X-Git-Tag: basepoints/gcc-13~4213 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1b54a7226368bf86361e5c9d8ae523193037a0ac;p=thirdparty%2Fgcc.git coroutines: Ensure co_await_exprs have TREE_SIDE_EFFECTS set [PR 101133]. Although it is not immediately evident from the symptoms, the PR is caused by a variable having a DECL_INITIAL() containing a co_await. This is not correct, since such expressions have side-effects. We were marking the overall co_await expression correctly, but if a consumer of that expression stripped out the underlying co_await_expr then the latter would not be properly marked. Fixed by marking both the underlying and any containing await expr with TREE_SIDE_EFFECTS. Also mark type-dependent co_await expressions. Signed-off-by: Iain Sandoe PR c++/101133 gcc/cp/ChangeLog: * coroutines.cc (build_co_await): Mark co_await_expr trees with TREE_SIDE_EFFECTS, also mark any containing expression. (finish_co_await_expr): Mark type-dependent co_await_expr trees with TREE_SIDE_EFFECTS. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr101133.C: New test. --- diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 876a14606f83..bff5b6343e54 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1117,13 +1117,15 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) a, e_proxy, o, awaiter_calls, build_int_cst (integer_type_node, (int) suspend_kind)); + TREE_SIDE_EFFECTS (await_expr) = true; if (te) { TREE_OPERAND (te, 1) = await_expr; + TREE_SIDE_EFFECTS (te) = true; await_expr = te; } - tree t = convert_from_reference (await_expr); - return t; + SET_EXPR_LOCATION (await_expr, loc); + return convert_from_reference (await_expr); } tree @@ -1149,8 +1151,13 @@ finish_co_await_expr (location_t kw, tree expr) co_await with the expression unchanged. */ tree functype = TREE_TYPE (current_function_decl); if (dependent_type_p (functype) || type_dependent_expression_p (expr)) - return build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr, - NULL_TREE, NULL_TREE, NULL_TREE, integer_zero_node); + { + tree aw_expr = build5_loc (kw, CO_AWAIT_EXPR, unknown_type_node, expr, + NULL_TREE, NULL_TREE, NULL_TREE, + integer_zero_node); + TREE_SIDE_EFFECTS (aw_expr) = true; + return aw_expr; + } /* We must be able to look up the "await_transform" method in the scope of the promise type, and obtain its return type. */ @@ -1187,14 +1194,7 @@ finish_co_await_expr (location_t kw, tree expr) } /* Now we want to build co_await a. */ - tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT); - if (op != error_mark_node) - { - TREE_SIDE_EFFECTS (op) = 1; - SET_EXPR_LOCATION (op, kw); - } - - return op; + return build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT); } /* Take the EXPR given and attempt to build: diff --git a/gcc/testsuite/g++.dg/coroutines/pr101133.C b/gcc/testsuite/g++.dg/coroutines/pr101133.C new file mode 100644 index 000000000000..6c6bc163251c --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr101133.C @@ -0,0 +1,31 @@ +#include +#include + +template +struct Awaiter +{ + bool await_ready() const { return false; } + void await_suspend(std::coroutine_handle<>) const {} + T await_resume() const { return T{}; } +}; + +struct ReturnObject +{ + struct promise_type + { + ReturnObject get_return_object() { return {}; } + std::suspend_never initial_suspend() noexcept { return {}; } + std::suspend_never final_suspend() noexcept { return {}; } + void return_void() {} + void unhandled_exception() {} + }; +}; + +ReturnObject f() +{ + auto a1 = Awaiter{}; + auto a2 = Awaiter{}; + + [[maybe_unused]] auto v1 = co_await a1; // ok + [[maybe_unused]] std::string v2 = co_await a2; // error +}