aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2020-04-27 23:55:00 +0100
committerIain Sandoe <iain@sandoe.co.uk>2020-04-27 23:58:07 +0100
commit174b6f735019a11017284aaa23962cebd3943c99 (patch)
treeb78b2db6fd38ea74975ece317e3488b08d485c1d
parentd8df7c404e233abb1e26d8b8370c460732904531 (diff)
downloadgcc-174b6f735019a11017284aaa23962cebd3943c99.zip
gcc-174b6f735019a11017284aaa23962cebd3943c99.tar.gz
gcc-174b6f735019a11017284aaa23962cebd3943c99.tar.bz2
coroutines: Fix for uses of structured binding [PR94701]
Structured binding makes use of the DECL_VALUE_EXPR fields in local variables. We need to recognise these and only amend the expression values, retaining the 'alias' value intact. gcc/cp/ChangeLog: 2020-04-27 Iain Sandoe <iain@sandoe.co.uk> PR c++/94701 * coroutines.cc (struct local_var_info): Add fields for static variables and those with DECL_VALUE_EXPR redirection. (transform_local_var_uses): Skip past typedefs and static vars and then account for redirected variables. (register_local_var_uses): Likewise. gcc/testsuite/ChangeLog: 2020-04-27 Iain Sandoe <iain@sandoe.co.uk> PR c++/94701 * g++.dg/coroutines/torture/local-var-06-structured-binding.C: New test.
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/coroutines.cc40
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/coroutines/torture/local-var-06-structured-binding.C55
4 files changed, 99 insertions, 11 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2b44b24..ae67a3e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2020-04-27 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/94701
+ * coroutines.cc (struct local_var_info): Add fields for static
+ variables and those with DECL_VALUE_EXPR redirection.
+ (transform_local_var_uses): Skip past typedefs and static vars
+ and then account for redirected variables.
+ (register_local_var_uses): Likewise.
+
2020-04-27 Jason Merrill <jason@redhat.com>
PR c++/90750
diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 0a5a0c9..36229c7 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -1774,6 +1774,8 @@ struct local_var_info
tree field_idx;
tree frame_type;
bool is_lambda_capture;
+ bool is_static;
+ bool has_value_expr_p;
location_t def_loc;
};
@@ -1819,7 +1821,7 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
NULL);
/* For capture proxies, this could include the decl value expr. */
- if (local_var.is_lambda_capture)
+ if (local_var.is_lambda_capture || local_var.has_value_expr_p)
{
tree ve = DECL_VALUE_EXPR (lvar);
cp_walk_tree (&ve, transform_local_var_uses, d, NULL);
@@ -1852,15 +1854,12 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
/* Leave lambda closure captures alone, we replace the *this
pointer with the frame version and let the normal process
- deal with the rest. */
- if (local_var.is_lambda_capture)
- {
- pvar = &DECL_CHAIN (*pvar);
- continue;
- }
-
- /* It's not used, but we can let the optimizer deal with that. */
- if (local_var.field_id == NULL_TREE)
+ deal with the rest.
+ Likewise, variables with their value found elsewhere.
+ Skip past unused ones too. */
+ if (local_var.is_lambda_capture
+ || local_var.has_value_expr_p
+ || local_var.field_id == NULL_TREE)
{
pvar = &DECL_CHAIN (*pvar);
continue;
@@ -1894,10 +1893,13 @@ transform_local_var_uses (tree *stmt, int *do_subtree, void *d)
for the promise and coroutine handle(s), to global vars or to compiler
temporaries. Skip past these, we will handle them later. */
local_var_info *local_var_i = lvd->local_var_uses->get (var_decl);
+
if (local_var_i == NULL)
return NULL_TREE;
- if (local_var_i->is_lambda_capture)
+ if (local_var_i->is_lambda_capture
+ || local_var_i->is_static
+ || local_var_i->has_value_expr_p)
return NULL_TREE;
/* This is our revised 'local' i.e. a frame slot. */
@@ -3390,6 +3392,16 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
tree lvtype = TREE_TYPE (lvar);
local_var.frame_type = lvtype;
local_var.field_idx = local_var.field_id = NULL_TREE;
+
+ /* Make sure that we only present vars to the tests below. */
+ if (TREE_CODE (lvar) == TYPE_DECL)
+ continue;
+
+ /* We don't move static vars into the frame. */
+ local_var.is_static = TREE_STATIC (lvar);
+ if (local_var.is_static)
+ continue;
+
lvd->local_var_seen = true;
/* If this var is a lambda capture proxy, we want to leave it alone,
and later rewrite the DECL_VALUE_EXPR to indirect through the
@@ -3398,6 +3410,12 @@ register_local_var_uses (tree *stmt, int *do_subtree, void *d)
if (local_var.is_lambda_capture)
continue;
+ /* If a variable has a value expression, then that's what needs
+ to be processed. */
+ local_var.has_value_expr_p = DECL_HAS_VALUE_EXPR_P (lvar);
+ if (local_var.has_value_expr_p)
+ continue;
+
/* Make names depth+index unique, so that we can support nested
scopes with identically named locals. */
tree lvname = DECL_NAME (lvar);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bc4d09b..b6e2f4f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-04-21 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR c++/94701
+ * g++.dg/coroutines/torture/local-var-06-structured-binding.C:
+ New test.
+
2020-04-27 Thomas Koenig <tkoenig@gcc.gnu.org>
PR fortran/93956
diff --git a/gcc/testsuite/g++.dg/coroutines/torture/local-var-06-structured-binding.C b/gcc/testsuite/g++.dg/coroutines/torture/local-var-06-structured-binding.C
new file mode 100644
index 0000000..ef3ff47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/torture/local-var-06-structured-binding.C
@@ -0,0 +1,55 @@
+// { dg-do run }
+
+#include "../coro.h"
+
+struct promise;
+
+struct future
+{
+ using promise_type = promise;
+};
+
+struct promise
+{
+ template<typename... Args>
+ promise (Args&... args) {}
+
+ coro::suspend_never initial_suspend() { return {}; }
+ coro::suspend_never final_suspend() { return {}; }
+
+ future get_return_object() { return {}; }
+
+ void return_value(int) {}
+ void unhandled_exception() {}
+};
+
+struct pair
+{
+ int i;
+};
+
+pair
+something ()
+{
+ return { 1 };
+}
+
+future
+my_coro ()
+{
+ auto ret = something ();
+
+ if (ret.i != 1)
+ abort ();
+
+ auto [ i ] = something ();
+ if (i != 1)
+ abort ();
+
+ co_return 1;
+}
+
+int main ()
+{
+ my_coro ();
+}