From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1698) id 09AB93858420; Fri, 17 Dec 2021 16:57:23 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 09AB93858420 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Iain D Sandoe To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-6045] coroutines: Pass lvalues to user-defined operator new [PR 100772]. X-Act-Checkin: gcc X-Git-Author: Iain Sandoe X-Git-Refname: refs/heads/master X-Git-Oldrev: 39d2ec41509e3b0d130215a65d7aacbd064b5532 X-Git-Newrev: 921942a8a106cb53994c21162922e4934eb3a3e0 Message-Id: <20211217165723.09AB93858420@sourceware.org> Date: Fri, 17 Dec 2021 16:57:23 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 17 Dec 2021 16:57:23 -0000 https://gcc.gnu.org/g:921942a8a106cb53994c21162922e4934eb3a3e0 commit r12-6045-g921942a8a106cb53994c21162922e4934eb3a3e0 Author: Iain Sandoe Date: Sun Oct 3 19:46:09 2021 +0100 coroutines: Pass lvalues to user-defined operator new [PR 100772]. 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. 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. Diff: --- gcc/cp/coroutines.cc | 8 +-- gcc/testsuite/g++.dg/coroutines/pr100772-a.C | 77 +++++++++++++++++++++++ gcc/testsuite/g++.dg/coroutines/pr100772-b.C | 93 ++++++++++++++++++++++++++++ 3 files changed, 174 insertions(+), 4 deletions(-) diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index c00672eeb6e..bcc91739702 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -4595,8 +4595,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. */ @@ -4614,10 +4614,10 @@ morph_fn_to_coro (tree orig, tree *resumer, tree *destroyer) this_ref = convert_to_reference (tt, this_ref, CONV_STATIC, LOOKUP_NORMAL , NULL_TREE, tf_warning_or_error); - vec_safe_push (args, this_ref); + vec_safe_push (args, convert_from_reference (this_ref)); } else - vec_safe_push (args, arg); + vec_safe_push (args, convert_from_reference (arg)); } /* Note the function selected; we test to see if it's NOTHROW. */ 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); +}