mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-24 12:41:09 +08:00
coroutines: Fix handling of target cleanup exprs [PR94883]
The problem here is that target cleanup expressions have been added to the initialisers for the awaitable (and returns of non-trivial values from await_suspend() calls. This is because the expansion of the co_await into its control flow is not apparent to the machinery adding the target cleanup expressions. The solution being tested is simply to recreate target expressions as the co_awaits are lowered. Teaching the machinery to handle walking co_await expressions in different ways at different points (outside the coroutine transformation) seems overly complex. gcc/cp/ChangeLog: 2020-04-30 Iain Sandoe <iain@sandoe.co.uk> PR c++/94883 * coroutines.cc (register_awaits): Update target expressions for awaitable and suspend handle initializers. gcc/testsuite/ChangeLog: 2020-04-30 Iain Sandoe <iain@sandoe.co.uk> PR c++/94883 * g++.dg/coroutines/pr94883-folly-2.C: New test.
This commit is contained in:
parent
b16fd5fd8a
commit
aa94a22f5c
gcc
@ -1,3 +1,10 @@
|
||||
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
PR c++/94883
|
||||
* coroutines.cc (register_awaits): Update target
|
||||
expressions for awaitable and suspend handle
|
||||
initializers.
|
||||
|
||||
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
PR c++/94879
|
||||
|
@ -2757,6 +2757,17 @@ register_awaits (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
|
||||
free (nam);
|
||||
}
|
||||
|
||||
tree o = TREE_OPERAND (aw_expr, 2); /* Initialiser for the frame var. */
|
||||
/* If this is a target expression, then we need to remake it to strip off
|
||||
any extra cleanups added. */
|
||||
if (TREE_CODE (o) == TARGET_EXPR)
|
||||
TREE_OPERAND (aw_expr, 2) = get_target_expr (TREE_OPERAND (o, 1));
|
||||
|
||||
tree v = TREE_OPERAND (aw_expr, 3);
|
||||
o = TREE_VEC_ELT (v, 1);
|
||||
if (TREE_CODE (o) == TARGET_EXPR)
|
||||
TREE_VEC_ELT (v, 1) = get_target_expr (TREE_OPERAND (o, 1));
|
||||
|
||||
register_await_info (aw_expr, aw_field_type, aw_field_nam);
|
||||
|
||||
/* Count how many awaits the current expression contains. */
|
||||
|
@ -1,3 +1,8 @@
|
||||
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
PR c++/94883
|
||||
* g++.dg/coroutines/pr94883-folly-2.C: New test.
|
||||
|
||||
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
PR c++/94879
|
||||
|
64
gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C
Normal file
64
gcc/testsuite/g++.dg/coroutines/pr94883-folly-2.C
Normal file
@ -0,0 +1,64 @@
|
||||
|
||||
namespace std {
|
||||
template <typename a, typename...> struct coroutine_traits : a {};
|
||||
template <typename = void> struct coroutine_handle;
|
||||
template <> struct coroutine_handle<> {};
|
||||
template <typename> struct coroutine_handle : coroutine_handle<> {};
|
||||
struct b {
|
||||
bool await_ready();
|
||||
void await_suspend(coroutine_handle<>);
|
||||
void await_resume();
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
template <typename d> auto ab(int ac, d ad) -> decltype(ad.e(ac));
|
||||
int f;
|
||||
class h {
|
||||
class j {
|
||||
public:
|
||||
bool await_ready();
|
||||
void await_suspend(std::coroutine_handle<>);
|
||||
void await_resume();
|
||||
};
|
||||
|
||||
public:
|
||||
void get_return_object();
|
||||
std::b initial_suspend();
|
||||
j final_suspend();
|
||||
void unhandled_exception();
|
||||
template <typename g>
|
||||
auto await_transform (g c) { return ab(f, c); }
|
||||
};
|
||||
template <typename, typename = int> class k {
|
||||
public:
|
||||
using promise_type = h;
|
||||
using i = std::coroutine_handle<>;
|
||||
class l {
|
||||
public:
|
||||
~l();
|
||||
operator bool();
|
||||
};
|
||||
class m {
|
||||
public:
|
||||
bool await_ready();
|
||||
i await_suspend(std::coroutine_handle<>);
|
||||
l await_resume();
|
||||
};
|
||||
class n {
|
||||
public:
|
||||
m e(int);
|
||||
};
|
||||
n ah();
|
||||
};
|
||||
|
||||
template <typename ai, typename aj, typename ak>
|
||||
k<aj>
|
||||
my_coro (k<aj, ak> am, ai) {
|
||||
if (auto an = co_await am.ah())
|
||||
;
|
||||
}
|
||||
|
||||
void foo () {
|
||||
k<int> a;
|
||||
my_coro (a, [] {});
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user