Commit 448c89d5 by Iain Sandoe

coroutines: Fix handling of artificial vars [PR94886]

The testcase ICEs because the range-based for generates three
artificial variables that need to be allocated to the coroutine
frame but, when walking the BIND_EXR that contains these, the
DECL_INITIAL for one of them refers to an entry appearing later,
which means that the frame entry hasn't been allocated when that
INITIAL is walked.

The solution is to defer walking the DECL_INITIAL/SIZE etc. until
all the BIND_EXPR vars have been processed.

gcc/cp/ChangeLog:

2020-04-30  Iain Sandoe  <iain@sandoe.co.uk>

	PR c++/94886
	* coroutines.cc (transform_local_var_uses): Defer walking
	the DECL_INITIALs of BIND_EXPR vars until all the frame
	allocations have been made.

gcc/testsuite/ChangeLog:

2020-04-30  Iain Sandoe  <iain@sandoe.co.uk>

	PR c++/94886
	* g++.dg/coroutines/pr94886-folly-3.C: New test.
parent aa94a22f
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94886
* coroutines.cc (transform_local_var_uses): Defer walking
the DECL_INITIALs of BIND_EXPR vars until all the frame
allocations have been made.
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94883
* coroutines.cc (register_awaits): Update target
expressions for awaitable and suspend handle
......
......@@ -1814,14 +1814,6 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
/* Re-write the variable's context to be in the actor func. */
DECL_CONTEXT (lvar) = lvd->context;
/* we need to walk some of the decl trees, which might contain
references to vars replaced at a higher level. */
cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
NULL);
cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
NULL);
/* For capture proxies, this could include the decl value expr. */
if (local_var.is_lambda_capture || local_var.has_value_expr_p)
{
......@@ -1843,6 +1835,22 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
lvd->actor_frame, fld_ref, NULL_TREE);
local_var.field_idx = fld_idx;
}
/* FIXME: we should be able to do this in the loop above, but (at least
for range for) there are cases where the DECL_INITIAL contains
forward references.
So, now we've built the revised var in the frame, substitute uses of
it in initializers and the bind expr body. */
for (lvar = BIND_EXPR_VARS (*stmt); lvar != NULL;
lvar = DECL_CHAIN (lvar))
{
/* we need to walk some of the decl trees, which might contain
references to vars replaced at a higher level. */
cp_walk_tree (&DECL_INITIAL (lvar), transform_local_var_uses, d,
NULL);
cp_walk_tree (&DECL_SIZE (lvar), transform_local_var_uses, d, NULL);
cp_walk_tree (&DECL_SIZE_UNIT (lvar), transform_local_var_uses, d,
NULL);
}
cp_walk_tree (&BIND_EXPR_BODY (*stmt), transform_local_var_uses, d, NULL);
/* Now we have processed and removed references to the original vars,
......
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94886
* g++.dg/coroutines/pr94886-folly-3.C: New test.
2020-04-30 Iain Sandoe <iain@sandoe.co.uk>
PR c++/94883
* g++.dg/coroutines/pr94883-folly-2.C: New test.
......
#include "coro.h"
#include "coro1-ret-int-yield-int.h"
#include <array>
coro1
my_coro ()
{
const std::array<int, 5> expectedValues = {{0, 3, 1, 4, 2}};
for (int expectedValue : expectedValues) {
co_yield expectedValue;
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment