[coro] Fix co_await of void type.
authorIain Sandoe <iain@sandoe.co.uk>
Tue, 21 Jan 2020 20:42:17 +0000 (20:42 +0000)
committerIain Sandoe <iain@sandoe.co.uk>
Tue, 21 Jan 2020 20:57:30 +0000 (20:57 +0000)
gcc/cp
2020-01-21  Iain Sandoe  <iain@sandoe.co.uk>
    Bin Cheng  <bin.cheng@linux.alibaba.com>

* coroutines.cc (coro_promise_type_found_p): Check for NULL return
from complete_type_or_else.
(register_param_uses): Likewise.
(build_co_await): Do not try to use complete_type_or_else for void
types, otherwise for incomplete types, check for NULL return from
complete_type_or_else.

gcc/testsuite
2020-01-21  Bin Cheng  <bin.linux@linux.alibaba.com>

* g++.dg/coroutines/co-await-void_type.C: New test.

gcc/cp/ChangeLog
gcc/cp/coroutines.cc
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/coroutines/co-await-void_type.C [new file with mode: 0644]

index 412702f9b62691213f492adf142170b820a6fd38..3fc1b31e5cd4bb475174c3a4d4c9d752ead973a1 100644 (file)
@@ -1,3 +1,13 @@
+2020-01-21  Iain Sandoe  <iain@sandoe.co.uk>
+           Bin Cheng  <bin.cheng@linux.alibaba.com>
+
+       * coroutines.cc (coro_promise_type_found_p): Check for NULL return
+       from complete_type_or_else.
+       (register_param_uses): Likewise.
+       (build_co_await): Do not try to use complete_type_or_else for void
+       types, otherwise for incomplete types, check for NULL return from
+       complete_type_or_else.
+
 2020-01-21  Jason Merrill  <jason@redhat.com>
 
        PR c++/91476 - anon-namespace reference temp clash between TUs.
index 8a8c1b9829b93759573699e06e6458f7c519e860..b99e7215639589f942ec6fa06520dc16d6d6eabf 100644 (file)
@@ -428,8 +428,9 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
 
       /* Complete this, we're going to use it.  */
       coro_info->handle_type = complete_type_or_else (handle_type, fndecl);
+
       /* Diagnostic would be emitted by complete_type_or_else.  */
-      if (coro_info->handle_type == error_mark_node)
+      if (!coro_info->handle_type)
        return false;
 
       /* Build a proxy for a handle to "self" as the param to
@@ -633,7 +634,13 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind)
   else
     o = a; /* This is most likely about to fail anyway.  */
 
-  tree o_type = complete_type_or_else (TREE_TYPE (o), o);
+  tree o_type = TREE_TYPE (o);
+  if (o_type && !VOID_TYPE_P (o_type))
+    o_type = complete_type_or_else (o_type, o);
+
+  if (!o_type)
+    return error_mark_node;
+
   if (TREE_CODE (o_type) != RECORD_TYPE)
     {
       error_at (loc, "awaitable type %qT is not a structure",
@@ -2730,6 +2737,10 @@ register_param_uses (tree *stmt, int *do_subtree ATTRIBUTE_UNUSED, void *d)
       if (!COMPLETE_TYPE_P (actual_type))
        actual_type = complete_type_or_else (actual_type, *stmt);
 
+      if (actual_type == NULL_TREE)
+       /* Diagnostic emitted by complete_type_or_else.  */
+       actual_type = error_mark_node;
+
       if (TREE_CODE (actual_type) == REFERENCE_TYPE)
        actual_type = build_pointer_type (TREE_TYPE (actual_type));
 
index e8561cca4122b7a254f1f6dbb9ee927e8e244f2d..f4f11a98ae7d740c2a3ca5eaa3e3eefc4fa72052 100644 (file)
@@ -1,3 +1,7 @@
+2020-01-21  Bin Cheng  <bin.linux@linux.alibaba.com>
+
+       * g++.dg/coroutines/co-await-void_type.C: New test.
+
 2020-01-21  Jakub Jelinek  <jakub@redhat.com>
 
        PR target/93333
diff --git a/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C b/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C
new file mode 100644 (file)
index 0000000..0bb8818
--- /dev/null
@@ -0,0 +1,44 @@
+//  { dg-additional-options "-std=c++17 -fsyntax-only -w" }
+
+#include <coroutine>
+
+class resumable {
+public:
+  struct promise_type;
+  using coro_handle = std::coroutine_handle<promise_type>;
+  resumable(coro_handle handle) : handle_(handle) {}
+  resumable(resumable&) = delete;
+  resumable(resumable&&) = delete;
+  bool resume() {
+    if (not handle_.done())
+      handle_.resume();
+    return not handle_.done();
+  }
+  int recent_val();
+  ~resumable() { handle_.destroy(); }
+private:
+  coro_handle handle_;
+};
+
+struct resumable::promise_type {
+  int value_;
+
+  using coro_handle = std::coroutine_handle<promise_type>;
+  auto get_return_object() {
+    return coro_handle::from_promise(*this);
+  }
+  auto initial_suspend() { return std::suspend_always(); }
+  auto final_suspend() { return std::suspend_always(); }
+  void yield_value(int v) { value_ = v; }
+  void unhandled_exception() {}
+};
+
+int resumable::recent_val(){return handle_.promise().value_;}
+
+resumable foo(int n){
+  int x = 1;
+  co_await std::suspend_always();
+  int y = 2;
+  co_yield n + x + y;  // { dg-error "awaitable type 'void' is not a structure" }
+}
+