@@ -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:
new file mode 100644
@@ -0,0 +1,31 @@
+#include <coroutine>
+#include <string>
+
+template<typename T>
+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<int>{};
+ auto a2 = Awaiter<std::string>{};
+
+ [[maybe_unused]] auto v1 = co_await a1; // ok
+ [[maybe_unused]] std::string v2 = co_await a2; // error
+}
Hi, 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. tested on x86_64, powerpc64le linux and x86_64 darwin, pushed to master as obvious, thanks, Iain Signed-off-by: Iain Sandoe <iain@sandoe.co.uk> 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. --- gcc/cp/coroutines.cc | 24 ++++++++--------- gcc/testsuite/g++.dg/coroutines/pr101133.C | 31 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr101133.C