public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Iain D Sandoe <iains@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc r13-4808] coroutines: Accept 'extern "C"' coroutines.
Date: Tue, 20 Dec 2022 19:32:36 +0000 (GMT)	[thread overview]
Message-ID: <20221220193236.1CA663858421@sourceware.org> (raw)

https://gcc.gnu.org/g:a6504f13a0509f3937bdcdf63bf76bed7d880b72

commit r13-4808-ga6504f13a0509f3937bdcdf63bf76bed7d880b72
Author: Iain Sandoe <iain@sandoe.co.uk>
Date:   Sat Dec 10 11:31:26 2022 +0000

    coroutines: Accept 'extern "C"' coroutines.
    
    'extern "C"' coroutines are permitted by the standard and expected to work
    (although constructing useful cases could be challenging). In order to
    permit this we need to arrange for the outlined helper functions to be
    named properly, even when no mangling is required.  To do this, we append
    the actor and destroy suffixes in all cases.
    
    Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>
    
    gcc/cp/ChangeLog:
    
            * mangle.cc (write_mangled_name): Append the helper function
            suffixes here...
            (write_encoding): ... rather than here.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/coroutines/torture/extern-c-coroutine.C: New test.

Diff:
---
 gcc/cp/mangle.cc                                   | 23 +++---
 .../g++.dg/coroutines/torture/extern-c-coroutine.C | 89 ++++++++++++++++++++++
 2 files changed, 101 insertions(+), 11 deletions(-)

diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index 074cf27ec7a..5789adcf680 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -805,6 +805,18 @@ write_mangled_name (const tree decl, bool top_level)
     write_string (".pre");
   else if (DECL_IS_POST_FN_P (decl))
     write_string (".post");
+
+  /* If this is a coroutine helper, then append an appropriate string to
+     identify which.  */
+  if (tree ramp = DECL_RAMP_FN (decl))
+    {
+      if (DECL_ACTOR_FN (ramp) == decl)
+	write_string (JOIN_STR "actor");
+      else if (DECL_DESTROY_FN (ramp) == decl)
+	write_string (JOIN_STR "destroy");
+      else
+	gcc_unreachable ();
+    }
 }
 
 /* Returns true if the return type of DECL is part of its signature, and
@@ -863,17 +875,6 @@ write_encoding (const tree decl)
 				mangle_return_type_p (decl),
 				d);
 
-      /* If this is a coroutine helper, then append an appropriate string to
-	 identify which.  */
-      if (tree ramp = DECL_RAMP_FN (decl))
-	{
-	  if (DECL_ACTOR_FN (ramp) == decl)
-	    write_string (JOIN_STR "actor");
-	  else if (DECL_DESTROY_FN (ramp) == decl)
-	    write_string (JOIN_STR "destroy");
-	  else
-	    gcc_unreachable ();
-	}
     }
 }
 
diff --git a/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C b/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C
new file mode 100644
index 00000000000..c178a80ee4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C
@@ -0,0 +1,89 @@
+#include <coroutine>
+#include <cstdio>
+
+#ifndef OUTPUT
+#  define PRINT(X)
+#  define PRINTF(X,...)
+#else
+#  define PRINT(X) puts(X)
+#  define PRINTF printf
+#endif
+
+struct future {
+  struct promise_type;
+  using handle_type = std::coroutine_handle<future::promise_type>;
+  handle_type handle;
+  future () : handle(0) {}
+  future (handle_type _handle)
+    : handle(_handle) {
+        PRINT("Created future object from handle");
+  }
+  future (const future &) = delete; // no copying
+  future (future &&s) : handle(s.handle) {
+	s.handle = nullptr;
+	PRINT("future mv ctor ");
+  }
+  future &operator = (future &&s) {
+	handle = s.handle;
+	s.handle = nullptr;
+	PRINT("future op=  ");
+	return *this;
+  }
+  ~future() {
+        PRINT("Destroyed future");
+        if ( handle )
+          handle.destroy();
+  }
+
+  struct promise_type {
+    void return_value (int v) {
+      PRINTF ("return_value (%d)\n", v);
+      vv = v;
+    }
+
+    std::suspend_always initial_suspend() noexcept { return {}; }
+    std::suspend_always final_suspend() noexcept { return {}; }
+    void unhandled_exception() {}
+    auto get_return_object() {return handle_type::from_promise (*this);}
+    
+    int get_value () { return vv; }
+  private:
+    int vv;
+  };
+  bool await_ready() { return false; }
+  void await_suspend(std::coroutine_handle<>) {}
+  void await_resume() {}
+};
+
+extern "C" future
+test () {
+  co_return 22;
+}
+
+extern "C" future
+f () noexcept
+{
+  PRINT ("future: about to return");
+  co_return 42;
+}
+
+int main ()
+{
+  PRINT ("main: create future");
+  future x = f ();
+  PRINT ("main: got future - resuming");
+  if (x.handle.done())
+    __builtin_abort ();
+  x.handle.resume();
+  PRINT ("main: after resume");
+  int y = x.handle.promise().get_value();
+  if ( y != 42 )
+    __builtin_abort ();
+  if (!x.handle.done())
+    {
+      PRINT ("main: apparently not done...");
+      __builtin_abort ();
+    }
+  PRINT ("main: returning");
+  return 0;
+}

                 reply	other threads:[~2022-12-20 19:32 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221220193236.1CA663858421@sourceware.org \
    --to=iains@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).