* [committed 1/2] libstdc++: Remove inheritance from std::coroutine_handle<> [LWG 3460]
@ 2020-10-20 10:38 Jonathan Wakely
2020-10-20 10:39 ` [committed 2/2] libstdc++: Define noop coroutine details private and inline [PR 95917] Jonathan Wakely
0 siblings, 1 reply; 2+ messages in thread
From: Jonathan Wakely @ 2020-10-20 10:38 UTC (permalink / raw)
To: libstdc++, gcc-patches; +Cc: Iain Sandoe
[-- Attachment #1: Type: text/plain, Size: 711 bytes --]
This removes the coroutine_handle<> base class from the primary template
and the noop_coroutine_promise explicit specialization. To preserve the
API various members are added, as they are no longer inherited from the
base class.
I've also tweaked some indentation and formatting, and replaced
subclause numbers from the standard with stable names like
[coroutine.handle.con].
libstdc++-v3/ChangeLog:
* include/std/coroutine (coroutine_handle<_Promise>): Remove
base class. Add constructors, conversions, accessors etc. as
proposed for LWG 3460.
(coroutine_handle<noop_coroutine_promise>): Likewise.
* testsuite/18_support/coroutines/lwg3460.cc: New test.
Tested powerpc64le-linux. Committed to trunk.
[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 11051 bytes --]
commit 2c2278f300cdd5f3181fe7df4dd1d869a67266a9
Author: Jonathan Wakely <jwakely@redhat.com>
Date: Tue Oct 20 11:18:35 2020
libstdc++: Remove inheritance from std::coroutine_handle<> [LWG 3460]
This removes the coroutine_handle<> base class from the primary template
and the noop_coroutine_promise explicit specialization. To preserve the
API various members are added, as they are no longer inherited from the
base class.
I've also tweaked some indentation and formatting, and replaced
subclause numbers from the standard with stable names like
[coroutine.handle.con].
libstdc++-v3/ChangeLog:
* include/std/coroutine (coroutine_handle<_Promise>): Remove
base class. Add constructors, conversions, accessors etc. as
proposed for LWG 3460.
(coroutine_handle<noop_coroutine_promise>): Likewise.
* testsuite/18_support/coroutines/lwg3460.cc: New test.
diff --git a/libstdc++-v3/include/std/coroutine b/libstdc++-v3/include/std/coroutine
index 468d1107557..6e1cf141579 100644
--- a/libstdc++-v3/include/std/coroutine
+++ b/libstdc++-v3/include/std/coroutine
@@ -87,7 +87,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
coroutine_handle<void>
{
public:
- // 17.12.3.1, construct/reset
+ // [coroutine.handle.con], construct/reset
constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {}
constexpr coroutine_handle(std::nullptr_t __h) noexcept
@@ -101,7 +101,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
public:
- // 17.12.3.2, export/import
+ // [coroutine.handle.export.import], export/import
constexpr void* address() const noexcept { return _M_fr_ptr; }
constexpr static coroutine_handle from_address(void* __a) noexcept
@@ -112,7 +112,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
public:
- // 17.12.3.3, observers
+ // [coroutine.handle.observers], observers
constexpr explicit operator bool() const noexcept
{
return bool(_M_fr_ptr);
@@ -120,7 +120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
- // 17.12.3.4, resumption
+ // [coroutine.handle.resumption], resumption
void operator()() const { resume(); }
void resume() const { __builtin_coro_resume(_M_fr_ptr); }
@@ -131,10 +131,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void* _M_fr_ptr;
};
- // 17.12.3.6 Comparison operators
- /// [coroutine.handle.compare]
- constexpr bool operator==(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ // [coroutine.handle.compare], comparison operators
+
+ constexpr bool
+ operator==(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return __a.address() == __b.address();
}
@@ -142,76 +142,107 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if _COROUTINES_USE_SPACESHIP
constexpr strong_ordering
operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
- { return std::compare_three_way()(__a.address(), __b.address()); }
+ {
+ return std::compare_three_way()(__a.address(), __b.address());
+ }
#else
// These are to enable operation with std=c++14,17.
- constexpr bool operator!=(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ constexpr bool
+ operator!=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return !(__a == __b);
}
- constexpr bool operator<(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ constexpr bool
+ operator<(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return less<void*>()(__a.address(), __b.address());
}
- constexpr bool operator>(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ constexpr bool
+ operator>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return __b < __a;
}
- constexpr bool operator<=(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ constexpr bool
+ operator<=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return !(__a > __b);
}
- constexpr bool operator>=(coroutine_handle<> __a,
- coroutine_handle<> __b) noexcept
+ constexpr bool
+ operator>=(coroutine_handle<> __a, coroutine_handle<> __b) noexcept
{
return !(__a < __b);
}
#endif
template <typename _Promise>
- struct coroutine_handle : coroutine_handle<>
+ struct coroutine_handle
{
- // 17.12.3.1, construct/reset
- using coroutine_handle<>::coroutine_handle;
+ // [coroutine.handle.con], construct/reset
- static coroutine_handle from_promise(_Promise& p)
+ constexpr coroutine_handle() noexcept { }
+
+ constexpr coroutine_handle(nullptr_t) noexcept { }
+
+ static coroutine_handle
+ from_promise(_Promise& __p)
{
coroutine_handle __self;
__self._M_fr_ptr
- = __builtin_coro_promise((char*) &p, __alignof(_Promise), true);
+ = __builtin_coro_promise((char*) &__p, __alignof(_Promise), true);
return __self;
}
- coroutine_handle& operator=(std::nullptr_t) noexcept
+ coroutine_handle& operator=(nullptr_t) noexcept
{
- coroutine_handle<>::operator=(nullptr);
+ _M_fr_ptr = nullptr;
return *this;
}
- // 17.12.3.2, export/import
- constexpr static coroutine_handle from_address(void* __a)
- {
- coroutine_handle __self;
- __self._M_fr_ptr = __a;
- return __self;
- }
+ // [coroutine.handle.export.import], export/import
- // 17.12.3.5, promise accesss
- _Promise& promise() const
- {
- void* __t
- = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false);
- return *static_cast<_Promise*>(__t);
- }
- };
+ constexpr void* address() const noexcept { return _M_fr_ptr; }
+
+ constexpr static coroutine_handle from_address(void* __a)
+ {
+ coroutine_handle __self;
+ __self._M_fr_ptr = __a;
+ return __self;
+ }
+
+ // [coroutine.handle.conv], conversion
+ constexpr operator coroutine_handle<>() const noexcept
+ { return coroutine_handle<>::from_address(address()); }
+
+ // [coroutine.handle.observers], observers
+ constexpr explicit operator bool() const noexcept
+ {
+ return bool(_M_fr_ptr);
+ }
+
+ bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); }
+
+ // [coroutine.handle.resumption], resumption
+ void operator()() const { resume(); }
+
+ void resume() const { __builtin_coro_resume(_M_fr_ptr); }
+
+ void destroy() const { __builtin_coro_destroy(_M_fr_ptr); }
+
+ // [coroutine.handle.promise], promise access
+ _Promise& promise() const
+ {
+ void* __t
+ = __builtin_coro_promise (_M_fr_ptr, __alignof(_Promise), false);
+ return *static_cast<_Promise*>(__t);
+ }
+
+ private:
+ void* _M_fr_ptr = nullptr;
+ };
/// [coroutine.noop]
struct noop_coroutine_promise
@@ -231,35 +262,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
// 17.12.4.1 Class noop_coroutine_promise
/// [coroutine.promise.noop]
template <>
- struct coroutine_handle<noop_coroutine_promise> : public coroutine_handle<>
+ struct coroutine_handle<noop_coroutine_promise>
{
- using _Promise = noop_coroutine_promise;
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3460. Unimplementable noop_coroutine_handle guarantees
+ // [coroutine.handle.noop.conv], conversion
+ constexpr operator coroutine_handle<>() const noexcept
+ { return coroutine_handle<>::from_address(address()); }
- public:
- // 17.12.4.2.1, observers
+ // [coroutine.handle.noop.observers], observers
constexpr explicit operator bool() const noexcept { return true; }
constexpr bool done() const noexcept { return false; }
- // 17.12.4.2.2, resumption
+ // [coroutine.handle.noop.resumption], resumption
void operator()() const noexcept {}
void resume() const noexcept {}
void destroy() const noexcept {}
- // 17.12.4.2.3, promise access
- _Promise& promise() const
- {
- return *static_cast<_Promise*>(
- __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false));
- }
+ // [coroutine.handle.noop.promise], promise access
+ noop_coroutine_promise& promise() const noexcept
+ { return __noop_coro_fr.__p; }
+
+ // [coroutine.handle.noop.address], address
+ constexpr void* address() const noexcept { return _M_fr_ptr; }
- // 17.12.4.2.4, address
private:
- friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
+ friend coroutine_handle noop_coroutine() noexcept;
- coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; }
+ coroutine_handle() = default;
+
+ void* _M_fr_ptr = (void*) &__noop_coro_fr;
};
using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
diff --git a/libstdc++-v3/testsuite/18_support/coroutines/lwg3460.cc b/libstdc++-v3/testsuite/18_support/coroutines/lwg3460.cc
new file mode 100644
index 00000000000..14a94ded95b
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/coroutines/lwg3460.cc
@@ -0,0 +1,54 @@
+// Copyright (C) 2020 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <coroutine>
+
+void
+test01()
+{
+ // LWG 3460. Unimplementable noop_coroutine_handle guarantees
+
+ static_assert( std::is_convertible_v<std::noop_coroutine_handle&,
+ std::coroutine_handle<>> );
+ static_assert( ! std::is_convertible_v<std::noop_coroutine_handle&,
+ std::coroutine_handle<>&> );
+ static_assert( ! std::is_assignable_v<std::noop_coroutine_handle&,
+ std::coroutine_handle<>> );
+
+ std::noop_coroutine_handle h = std::noop_coroutine();
+ std::coroutine_handle<> h2 = h;
+ h2(); // no-op
+ h2.resume(); // no-op
+ h2.destroy(); // no-op
+}
+
+void
+test02()
+{
+ // LWG 3469. Precondition of coroutine_handle::promise may be insufficient
+
+ struct P1 { };
+ struct P2 { };
+
+ static_assert( ! std::is_assignable_v<std::coroutine_handle<P1>&,
+ std::coroutine_handle<>> );
+ static_assert( ! std::is_assignable_v<std::coroutine_handle<P1>&,
+ std::coroutine_handle<P2>> );
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* [committed 2/2] libstdc++: Define noop coroutine details private and inline [PR 95917]
2020-10-20 10:38 [committed 1/2] libstdc++: Remove inheritance from std::coroutine_handle<> [LWG 3460] Jonathan Wakely
@ 2020-10-20 10:39 ` Jonathan Wakely
0 siblings, 0 replies; 2+ messages in thread
From: Jonathan Wakely @ 2020-10-20 10:39 UTC (permalink / raw)
To: libstdc++, gcc-patches; +Cc: Iain Sandoe
libstdc++: Define noop coroutine details private and inline [PR 95917]
This moves the __noop_coro_frame type, the __noop_coro_fr global
variable, and the __dummy_resume_destroy function from namespace scope,
replacing them with private members of the specialization
coroutine_handle<noop_coroutine_promise>.
The function and variable are also declared inline, so that they
generate no code unless used.
libstdc++-v3/ChangeLog:
PR libstdc++/95917
* include/std/coroutine (__noop_coro_frame): Replace with
noop_coroutine_handle::__frame.
(__dummy_resume_destroy): Define inline in __frame.
(__noop_coro_fr): Replace with noop_coroutine_handle::_S_fr
and define as inline.
* testsuite/18_support/coroutines/95917.cc: New test.
Tested powerpc64le-linux. Committed to trunk.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2020-10-20 10:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-20 10:38 [committed 1/2] libstdc++: Remove inheritance from std::coroutine_handle<> [LWG 3460] Jonathan Wakely
2020-10-20 10:39 ` [committed 2/2] libstdc++: Define noop coroutine details private and inline [PR 95917] Jonathan Wakely
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).