From patchwork Fri Nov 5 15:49:09 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Iain Sandoe X-Patchwork-Id: 47121 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 4092A3858428 for ; Fri, 5 Nov 2021 15:49:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4092A3858428 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636127387; bh=dGYIhkU7IJGOQ8pj0L/8AauYr08LPGmDCtoFwG3KfsM=; h=To:Subject:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:Cc:From; b=X57zcd+Hq49KzbVRXcRc3y6N5GUI9mVSmIeqRR0LmAxWp49EN9G3bC+1/8NrJmgMN exrAQI8FAah+TETAhsq0fsPs7XBkOJAng3TWCgpGVbLvYAYRJ1CkC9mDf3iVano14h cj8fhXoVzsLi0lrT7XXqJs7jiiuxLM2STIaDRsTc= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x432.google.com (mail-wr1-x432.google.com [IPv6:2a00:1450:4864:20::432]) by sourceware.org (Postfix) with ESMTPS id 01E813858D28 for ; Fri, 5 Nov 2021 15:49:17 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 01E813858D28 Received: by mail-wr1-x432.google.com with SMTP id r8so14369281wra.7 for ; Fri, 05 Nov 2021 08:49:16 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :mime-version:content-transfer-encoding; bh=dGYIhkU7IJGOQ8pj0L/8AauYr08LPGmDCtoFwG3KfsM=; b=NNjIGGAUwrayqu6dFabP5+U/wbB3f7BR1xTkkk4xvRqKYr+rFzGL3G3Fzk0nTM/6iK cSa022DvyBSX6hUWL5uMhfPE696RZ3Chmo0bJ0iWUUkdOf8bavV+qKQddy7yhzC5unqr W61TxT1aNV8LDzfBIO54iGZkWHkuHuLJlMycdnZgYYSMkcIt+QSvCSonx4RXlBVOdaHB d8mhB7ZXpJJ7iAtmoQs2+pN0Kjq7o+Q6wj75366GURIYaY6w1IyHzKUf4gnZfKKqB3g+ qg3rMte+DADPsTeCNpWKPpLGnEKhc2dFCt0A7T71+4fFO/sdRx+nlqJqbAbQR59V2dZj TEvw== X-Gm-Message-State: AOAM531Mnr3fPk6/6WvsrhXIpczVZWj47KHVcEPRiYFjjt4dtms1XC2Z 0fqwrb7rXRbSMiDOyWIXU4YM8PWMxkU= X-Google-Smtp-Source: ABdhPJyZi0i4P5Rflwpg5+K1iggquwHjFEocG+Mhyq9uwfZOJRSTzt6QTeVsLDp5jkuayJzs4I6xHg== X-Received: by 2002:a5d:550f:: with SMTP id b15mr65974700wrv.212.1636127355941; Fri, 05 Nov 2021 08:49:15 -0700 (PDT) Received: from localhost.localdomain (host81-138-1-83.in-addr.btopenworld.com. [81.138.1.83]) by smtp.gmail.com with ESMTPSA id c1sm8209551wrt.14.2021.11.05.08.49.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 05 Nov 2021 08:49:15 -0700 (PDT) X-Google-Original-From: Iain Sandoe To: gcc-patches@gcc.gnu.org Subject: [PATCH] coroutines: Pass lvalues to user-defined operator new [PR 100772]. Date: Fri, 5 Nov 2021 15:49:09 +0000 Message-Id: <20211105154909.91162-1-iain@sandoe.co.uk> X-Mailer: git-send-email 2.24.3 (Apple Git-128) MIME-Version: 1.0 X-Spam-Status: No, score=-8.5 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.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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 Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The wording of the standard has been clarified to be explicit that the the parameters to any user-defined operator-new in the promise class should be lvalues. tested on x86_64 darwin, linux, OK for master and backports? thanks Iain Signed-off-by: Iain Sandoe PR c++/100772 gcc/cp/ChangeLog: * coroutines.cc (morph_fn_to_coro): Convert function parms from reference before constructing any operator-new args list. gcc/testsuite/ChangeLog: * g++.dg/coroutines/pr100772-a.C: New test. * g++.dg/coroutines/pr100772-b.C: New test. --- gcc/cp/coroutines.cc | 6 +- gcc/testsuite/g++.dg/coroutines/pr100772-a.C | 77 ++++++++++++++++ gcc/testsuite/g++.dg/coroutines/pr100772-b.C | 93 ++++++++++++++++++++ 3 files changed, 174 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/pr100772-a.C create mode 100644 gcc/testsuite/g++.dg/coroutines/pr100772-b.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index 6db4b70f028..ab211201255 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -4602,8 +4602,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) If the lookup finds an allocation function in the scope of the promise type, overload resolution is performed on a function call created by assembling an argument list. The first argument is the amount of space - requested, and has type std::size_t. The succeeding arguments are - those of the original function. */ + requested, and has type std::size_t. The lvalues p1...pn are the + succeeding arguments.. */ vec *args = make_tree_vector (); vec_safe_push (args, resizeable); /* Space needed. */ @@ -4623,6 +4623,8 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) tf_warning_or_error); vec_safe_push (args, this_ref); } + else if (parm_i->rv_ref || parm_i->pt_ref) + vec_safe_push (args, convert_from_reference (arg)); else vec_safe_push (args, arg); } diff --git a/gcc/testsuite/g++.dg/coroutines/pr100772-a.C b/gcc/testsuite/g++.dg/coroutines/pr100772-a.C new file mode 100644 index 00000000000..a325d384fc3 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr100772-a.C @@ -0,0 +1,77 @@ +// { dg-additional-options "-fsyntax-only " } +#ifdef __clang__ +#include +namespace std { + using namespace std::experimental; +} +#else +#include +#endif + +struct Task +{ + struct promise_type + { + void return_void() const noexcept {} + + void* operator new(std::size_t, auto &&...args) noexcept + { + static_assert(sizeof...(args) > 0); + static_assert(sizeof...(args) == 2); + + return nullptr; + } + + void operator delete(void *, std::size_t) noexcept + { + } + + static Task get_return_object_on_allocation_failure() noexcept + { + return {}; + } + + Task get_return_object() noexcept + { + return Task{ *this }; + } + + std::suspend_always initial_suspend() noexcept + { + return {}; + } + + std::suspend_always final_suspend() noexcept + { + return {}; + } + + void unhandled_exception() noexcept {} + }; + + using promise_handle = std::coroutine_handle; + + Task() = default; + Task(promise_type & promise) noexcept + : m_handle{ promise_handle::from_promise(promise) } + {} + + ~Task() + { + if (m_handle.address()) { m_handle.destroy(); } + } + + promise_handle m_handle{}; +}; + + +Task Foo(auto && ... args) noexcept +{ + co_return; +} + +int main() +{ + int v; + Foo(v, 2134); +} diff --git a/gcc/testsuite/g++.dg/coroutines/pr100772-b.C b/gcc/testsuite/g++.dg/coroutines/pr100772-b.C new file mode 100644 index 00000000000..6cdf8d1e529 --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/pr100772-b.C @@ -0,0 +1,93 @@ +#ifdef __clang__ +#include +namespace std { + using namespace std::experimental; +} +#else +#include +#endif +#include +#include +#include // needed for abi::__cxa_demangle +#include + +std::shared_ptr cppDemangle(const char *abiName) +{ + int status; + char *ret = abi::__cxa_demangle(abiName, 0, 0, &status); + + /* NOTE: must free() the returned char when done with it! */ + std::shared_ptr retval; + retval.reset( (char *)ret, [](char *mem) { if (mem) free((void*)mem); } ); + return retval; +} + +template +struct Id{}; +struct Task +{ + struct promise_type + { + void return_void() const noexcept {} + + static void is_int (std::string x) { + if (x != "Id") + abort() ; + } + template + void* operator new(std::size_t len, Args ...args) noexcept + { + (is_int (cppDemangle(typeid(Id).name()).get()), ...); + (std::puts (cppDemangle(typeid(Id).name()).get()), ...); + return nullptr; + } + + static Task get_return_object_on_allocation_failure() noexcept + { + return {}; + } + + Task get_return_object() noexcept + { + return Task{ *this }; + } + + std::suspend_always initial_suspend() noexcept + { + return {}; + } + + std::suspend_always final_suspend() noexcept + { + return {}; + } + + void unhandled_exception() noexcept {} + }; + + using promise_handle = std::coroutine_handle; + + Task() = default; + Task(promise_type & promise) noexcept + : m_handle{ promise_handle::from_promise(promise) } + {} + + ~Task() + { + if (m_handle.address()) { m_handle.destroy(); } + } + + promise_handle m_handle{}; +}; + + +Task Foo(auto && ... args) noexcept +{ + co_return; +} + +int main() +{ + int v; + Foo(v, 2134); +}