coroutines: Fix cases where proxy variables are used [PR94879]
authorIain Sandoe <iain@sandoe.co.uk>
Mon, 27 Apr 2020 14:21:25 +0000 (15:21 +0100)
committerIain Sandoe <iain@sandoe.co.uk>
Thu, 30 Apr 2020 14:56:44 +0000 (15:56 +0100)
There are several places where the handling of a variable
declaration depends on whether it corresponds to a compiler
temporary, or to some other entity.  We were testing that var
decls were artificial in determining this.  However, proxy vars
are also artificial so that this is not sufficient.  The solution
is to exclude variables with a DECL_VALUE_EXPR as well, since
the value variable will not be a temporary.

gcc/cp/ChangeLog:

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

PR c++/94879
* coroutines.cc (build_co_await): Account for variables
with DECL_VALUE_EXPRs.
(captures_temporary): Likewise.
(register_awaits): Likewise.

gcc/testsuite/ChangeLog:

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

PR c++/94879
* g++.dg/coroutines/pr94879-folly-1.C: New test.

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

index cbedbabe3a64efba9a4cf4256bafbc1b8349e50c..3172f949ee9b3204e50334d10cc1230c74447c9a 100644 (file)
@@ -1,3 +1,11 @@
+2020-04-30  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR c++/94879
+       * coroutines.cc (build_co_await): Account for variables
+       with DECL_VALUE_EXPRs.
+       (captures_temporary): Likewise.
+       (register_awaits): Likewise.
+
 2020-04-29  Patrick Palka  <ppalka@redhat.com>
 
        PR c++/94830
index 7bb3e98fe6c8df4a90c9244610e423e4fec86e8c..e2dbeabf48b0f2a32a5669d7154da81f7ab8b18e 100644 (file)
@@ -748,7 +748,8 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
   if (INDIRECT_REF_P (e_proxy))
     e_proxy = TREE_OPERAND (e_proxy, 0);
   if (TREE_CODE (e_proxy) == PARM_DECL
-      || (TREE_CODE (e_proxy) == VAR_DECL && !DECL_ARTIFICIAL (e_proxy)))
+      || (VAR_P (e_proxy) && (!DECL_ARTIFICIAL (e_proxy)
+                             || DECL_HAS_VALUE_EXPR_P (e_proxy))))
     e_proxy = o;
   else
     {
@@ -2659,7 +2660,8 @@ captures_temporary (tree *stmt, int *do_subtree, void *d)
        }
 
       /* This isn't a temporary.  */
-      if ((TREE_CODE (parm) == VAR_DECL && !DECL_ARTIFICIAL (parm))
+      if ((VAR_P (parm)
+          && (!DECL_ARTIFICIAL (parm) || DECL_HAS_VALUE_EXPR_P (parm)))
          || TREE_CODE (parm) == PARM_DECL
          || TREE_CODE (parm) == NON_LVALUE_EXPR)
        continue;
@@ -2742,7 +2744,8 @@ register_awaits (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
   if (INDIRECT_REF_P (aw))
     aw = TREE_OPERAND (aw, 0);
   if (TREE_CODE (aw) == PARM_DECL
-      || (TREE_CODE (aw) == VAR_DECL && !DECL_ARTIFICIAL (aw)))
+      || (VAR_P (aw) && (!DECL_ARTIFICIAL (aw)
+                        || DECL_HAS_VALUE_EXPR_P (aw))))
     ; /* Don't make an additional copy.  */
   else
     {
index 49f00426e06b192c0c62d832d9261d7fd63b5f8e..7f39eda02779ddc316c9d5d31e67e8463095d20a 100644 (file)
@@ -1,3 +1,8 @@
+2020-04-30  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR c++/94879
+       * g++.dg/coroutines/pr94xxx-folly-1.C: New test.
+
 2020-04-30  Marek Polacek  <polacek@redhat.com>
 
        PR c++/94775
diff --git a/gcc/testsuite/g++.dg/coroutines/pr94879-folly-1.C b/gcc/testsuite/g++.dg/coroutines/pr94879-folly-1.C
new file mode 100644 (file)
index 0000000..7d66ce0
--- /dev/null
@@ -0,0 +1,49 @@
+//  { dg-additional-options  "-fpreprocessed -w" }
+
+namespace std {
+template <typename a> a b(a &&);
+template <typename c> struct d { c e; };
+template <typename f, typename> struct coroutine_traits : f {};
+template <typename = void> struct coroutine_handle;
+template <> struct coroutine_handle<> {};
+template <typename> struct coroutine_handle : coroutine_handle<> {};
+struct g {};
+} // namespace std
+
+class h {};
+class i {
+  i(i &&);
+};
+
+namespace ac {
+template <typename> class ad {
+public:
+  bool await_ready();
+  void await_resume();
+  void await_suspend(std::coroutine_handle<>);
+  i ae;
+};
+} // namespace ac
+
+template <typename ab> ac::ad<ab> operator co_await(ab);
+class j {
+  class l {};
+
+public:
+  std::g initial_suspend();
+  l final_suspend();
+};
+class m : public j {
+public:
+  void get_return_object();
+  void unhandled_exception();
+};
+class n {
+public:
+  using promise_type = m;
+};
+std::d<h> k;
+void a() {
+  auto am = k;
+  [&]() -> n { co_await std::b(am.e); };
+}