Hi Nathan,

This corrects my mixup between the error returns for complete_type and
complete_type_or_else, spotted by Jakub,

I have included Bin’s change that makes the coro-specific error message
fire if a void type is provided for this.

Additional comments below.

Iain Sandoe <i...@sandoe.co.uk> wrote:

> Bin.Cheng <amker.ch...@gmail.com> wrote:
> 
>> On Mon, Jan 20, 2020 at 6:31 PM Iain Sandoe <i...@sandoe.co.uk> wrote:

>>> Bin.Cheng <amker.ch...@gmail.com> wrote:
>>> 

>>>   tree o_type = TREE_TYPE (o);
>>> -  if (!VOID_TYPE_P (o_type))
>>> -    o_type = complete_type_or_else (TREE_TYPE (o), o);
>>> +  if (o_type && !VOID_TYPE_P (o_type) && !COMPLETE_TYPE_P (o_type))
>> IIUC, Jakub doesn't like checking void type specially here?
> 
> that is necessary if we want the coro-specific diagnostic (which is more 
> meaningful
> than the vanilla void one) however, if there’s opposition to that, I don’t 
> have such a
> strong opinion.

Note, we cannot eliminate the following code for the diagnostic check; we still 
have to
verify that complete types are suitable.  Bin’s addition makes that warning 
fire for void
types too.

OK for trunk?
thanks
Iain


    [coro] Fix co_await of void type.
    
    gcc/cp
    2020-01-21  Iain Sandoe  <i...@sandoe.co.uk>
                Bin Cheng  <bin.ch...@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.ch...@linux.alibaba.com>
    
            * g++.dg/coroutines/co-await-void_type.C: New test.

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 8a8c1b9829b..aea341604b9 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -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) && !COMPLETE_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));
 
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
index 00000000000..0bb8818133e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/co-await-void_type.C
@@ -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" }
+}
+



Reply via email to