coroutines: Fix handling of artificial vars [PR94886]
authorIain Sandoe <iain@sandoe.co.uk>
Thu, 30 Apr 2020 09:42:36 +0000 (10:42 +0100)
committerIain Sandoe <iain@sandoe.co.uk>
Thu, 30 Apr 2020 15:00:39 +0000 (16:00 +0100)
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.

gcc/cp/ChangeLog
gcc/cp/coroutines.cc
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/coroutines/pr94886-folly-3.C [new file with mode: 0644]

index 62f997eb4592e96bb9bdef4dc4a7101724adb82e..1fa0e123cb11111b003ec9766e63396be6ae59bf 100644 (file)
@@ -1,3 +1,10 @@
+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
index cb9074e4c170b4df86e462ad19ea0240020d84f1..e90d3d5a3b39dabee0e48c9ab2ef6cb0780559ea 100644 (file)
@@ -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,
index 369ce423fbcfefb56fb5624d999461ce3f082999..7d5ae7533400af68f82c8ea40c580c0420a01bd3 100644 (file)
@@ -1,3 +1,8 @@
+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
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 (file)
index 0000000..d7bd2c1
--- /dev/null
@@ -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;
+  }
+}