Hi Another case found when building the folly experimental coros stuff. tested on x86_64-darwin so far, OK for master after testing on x86_64-linux? thanks Iain
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 <i...@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 <i...@sandoe.co.uk> PR c++/94886 * g++.dg/coroutines/pr94886-folly-3.C: New test. --- gcc/cp/coroutines.cc | 21 ++++++++++++------- .../g++.dg/coroutines/pr94886-folly-3.C | 15 +++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr94886-folly-3.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 7bb3e98fe6c..1bc4bf2e45b 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -1813,14 +1813,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) { @@ -1842,6 +1834,19 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d) lvd->actor_frame, fld_ref, NULL_TREE); local_var.field_idx = fld_idx; } + /* 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, diff --git a/gcc/testsuite/g++.dg/coroutines/pr94886-folly-3.C b/gcc/testsuite/g++.dg/coroutines/pr94886-folly-3.C new file mode 100644 index 00000000000..d7bd2c17d4a --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr94886-folly-3.C @@ -0,0 +1,15 @@ + +#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; + } +} -- 2.24.1