[gcc(refs/vendors/ARM/heads/arm-perf-staging)] coroutines: Fix for uses of structured binding [PR94701]

Tamar Christina tnfchris@gcc.gnu.org
Fri Jul 17 15:00:56 GMT 2020


https://gcc.gnu.org/g:174b6f735019a11017284aaa23962cebd3943c99

commit 174b6f735019a11017284aaa23962cebd3943c99
Author: Iain Sandoe <iain@sandoe.co.uk>
Date:   Mon Apr 27 23:55:00 2020 +0100

    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.

Diff:
---
 gcc/cp/ChangeLog                                   |  9 ++++
 gcc/cp/coroutines.cc                               | 40 +++++++++++-----
 gcc/testsuite/ChangeLog                            |  6 +++
 .../torture/local-var-06-structured-binding.C      | 55 ++++++++++++++++++++++
 4 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 2b44b24461f..ae67a3e6c63 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 0a5a0c9b1d2..36229c77b4e 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 bc4d09b2048..b6e2f4f819f 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 00000000000..ef3ff47c16f
--- /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 ();
+}


More information about the Gcc-cvs mailing list