From patchwork Sat Dec 10 11:37:44 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 61749 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 35051384F4B9 for ; Sat, 10 Dec 2022 11:38:17 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 35051384F4B9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1670672297; bh=CIFyLT+4aXoef0awI1bTPCl6gZIZhSwvLQ1hkoI8doc=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=K1WIF560seJh7G4d8iQ7x9+cZGAO9pWhmT8B36Iy4oY8jW8wI16BJbjZj6g8hw7/D R0E3CT1b6mbSthBnxk6vWRK5CgjpCSkX3oZgOqmMg8vO6/EKEWfbZnkteQkOS7CTlE hrQw2D3GHGwq7UJi53Ep6qBGqeXKgHyp9FZXrLFM= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com [IPv6:2a00:1450:4864:20::32f]) by sourceware.org (Postfix) with ESMTPS id 446A838500AC for ; Sat, 10 Dec 2022 11:37:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 446A838500AC Received: by mail-wm1-x32f.google.com with SMTP id r7-20020a1c4407000000b003d1e906ca23so442924wma.3 for ; Sat, 10 Dec 2022 03:37:47 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:reply-to:message-id:date :subject:cc:to:from:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=CIFyLT+4aXoef0awI1bTPCl6gZIZhSwvLQ1hkoI8doc=; b=1ymKl7n23M0v17Lnb9pWn/pBwdHsB+Om1B4JsXwQIjAjzc3y0fDIpUnvmsyTJz5XCM wZamvHDgSyrQ4/iXK76LpgJTQ3B9A31Ygy27LXvKfTs8YfOWqMzgqKINk4GMfFaZb272 yh6D3Yn1b0pojFBo7MhwWa7bePqIRc6w0AYqP9x08Qrh9govsXDRwnRATPhPkfnBwPg0 oO+fwbDOp7nynd5/BxhAxgTgqBZVmys3XWDrlzauIttWb5BOaflDJAxLq+QKHbJ97WkF wiYr/pTo4/bNR6KrGSKlSfAx11n5OrDxa05E6EYYPDgVinFUwDglie8k2Hk8+YJpXnMw 7hmg== X-Gm-Message-State: ANoB5pl/AKgS5gv38WpH9Ug4sdeJdD7VAvxxYP2xsssnKFinKch8mtn/ s6GjVwLMvys2/WkLOrCHZVazvpyZQpM= X-Google-Smtp-Source: AA0mqf6FsbEmO8NL1abBHbgNNpTQMGdD5bmVZuErUDrqUrJKAwEf1jh5qZ7Z4k7YkwbuRiPO9vS3Og== X-Received: by 2002:a05:600c:1da8:b0:3d1:e04f:9bf1 with SMTP id p40-20020a05600c1da800b003d1e04f9bf1mr7616765wms.35.1670672265872; Sat, 10 Dec 2022 03:37:45 -0800 (PST) Received: from localhost.localdomain (host81-138-1-83.in-addr.btopenworld.com. [81.138.1.83]) by smtp.gmail.com with ESMTPSA id az25-20020a05600c601900b003cf9bf5208esm2653355wmb.19.2022.12.10.03.37.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 10 Dec 2022 03:37:45 -0800 (PST) X-Google-Original-From: Iain Sandoe To: gcc-patches@gcc.gnu.org Subject: [PATCH] coroutines: Accept 'extern "C"' coroutines. Date: Sat, 10 Dec 2022 11:37:44 +0000 Message-Id: <20221210113744.38708-1-iain@sandoe.co.uk> X-Mailer: git-send-email 2.37.1 (Apple Git-137.1) MIME-Version: 1.0 X-Spam-Status: No, score=-8.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Iain Sandoe via Gcc-patches From: Iain Sandoe Reply-To: iain@sandoe.co.uk Cc: Iain Sandoe , jason@redhat.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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 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. Signed-off-by: Iain Sandoe --- 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 +#include + +#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; + 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; +}