public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] coroutines: Accept 'extern "C"' coroutines.
@ 2022-12-10 11:37 Iain Sandoe
  2022-12-17 13:40 ` [PATCH v2] " Iain Sandoe
  0 siblings, 1 reply; 3+ messages in thread
From: Iain Sandoe @ 2022-12-10 11:37 UTC (permalink / raw)
  To: gcc-patches; +Cc: jason

This came up in discussion and was relatively easy to 'fix' although it remains
to be seen whether it was really intended.  Tested on x86_64-darwin21. 
OK for trunk?
Iain

--- >8 ---

As of now the standard does not appear to forbid this, and clang accepts.
The use-cases are somewhat unclear (question placed with the designers) but
implemented here for sake of compatibility.

Signed-off-by: Iain Sandoe <iain@sandoe.co.uk>

gcc/cp/ChangeLog:

	* coroutines.cc (coro_build_actor_or_destroy_function): Accept
	coroutines that are 'extern "C"' and build unmangled names for
	the actor and destroy functions.

gcc/testsuite/ChangeLog:

	* g++.dg/coroutines/torture/extern-c-coroutine.C: New test.
---
 gcc/cp/coroutines.cc                          | 12 +++
 .../coroutines/torture/extern-c-coroutine.C   | 89 +++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/coroutines/torture/extern-c-coroutine.C

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index 3f23317a315..c1a0d6c2283 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc
@@ -32,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "gcc-rich-location.h"
 #include "hash-map.h"
+#include "cgraph.h"
 
 static bool coro_promise_type_found_p (tree, location_t);
 
@@ -4060,6 +4061,17 @@ coro_build_actor_or_destroy_function (tree orig, tree fn_type,
       else
 	info->destroy_decl = fn;
     }
+  /* If the function is extern "C" the mangler will not be called.  */
+  if (DECL_EXTERN_C_P (orig))
+    {
+      /* clone_function_name () picks up the name from DECL_ASSEMBLER_NAME
+	 which is not yet set here.  */
+      SET_DECL_ASSEMBLER_NAME (fn, DECL_NAME (orig));
+      if (actor_p)
+	SET_DECL_ASSEMBLER_NAME (fn, clone_function_name (fn, "actor"));
+      else
+	SET_DECL_ASSEMBLER_NAME (fn, clone_function_name (fn, "destroy"));
+    }
   return fn;
 }
 
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;
+}
-- 
2.37.1 (Apple Git-137.1)


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-12-19 15:54 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-10 11:37 [PATCH] coroutines: Accept 'extern "C"' coroutines Iain Sandoe
2022-12-17 13:40 ` [PATCH v2] " Iain Sandoe
2022-12-19 15:54   ` Jason Merrill

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).