Add <experimental/coroutine>
This patch adds the library portions of the coroutines PDTS, which should now be supported by Clang. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@303836 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -452,6 +452,11 @@ add_compile_flags_if_supported(-nostdinc++)
|
|||||||
# the dylib when get ODR used by another function.
|
# the dylib when get ODR used by another function.
|
||||||
add_compile_flags_if_supported(-fvisibility-inlines-hidden)
|
add_compile_flags_if_supported(-fvisibility-inlines-hidden)
|
||||||
|
|
||||||
|
if (LIBCXX_CONFIGURE_IDE)
|
||||||
|
# This simply allows IDE to process <experimental/coroutine>
|
||||||
|
add_compile_flags_if_supported(-fcoroutines-ts)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Let the library headers know they are currently being used to build the
|
# Let the library headers know they are currently being used to build the
|
||||||
# library.
|
# library.
|
||||||
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
|
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
|
||||||
|
|||||||
@@ -44,6 +44,13 @@
|
|||||||
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM \
|
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM \
|
||||||
} } _LIBCPP_END_NAMESPACE_EXPERIMENTAL
|
} } _LIBCPP_END_NAMESPACE_EXPERIMENTAL
|
||||||
|
|
||||||
|
#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES \
|
||||||
|
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace coroutines_v1 {
|
||||||
|
|
||||||
|
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES \
|
||||||
|
} _LIBCPP_END_NAMESPACE_EXPERIMENTAL
|
||||||
|
|
||||||
|
#define _VSTD_CORO _VSTD_EXPERIMENTAL::coroutines_v1
|
||||||
|
|
||||||
#define _VSTD_FS ::std::experimental::filesystem::v1
|
#define _VSTD_FS ::std::experimental::filesystem::v1
|
||||||
|
|
||||||
|
|||||||
260
include/experimental/coroutine
Normal file
260
include/experimental/coroutine
Normal file
@@ -0,0 +1,260 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------- coroutine -----------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_EXPERIMENTAL_COROUTINE
|
||||||
|
#define _LIBCPP_EXPERIMENTAL_COROUTINE
|
||||||
|
|
||||||
|
/**
|
||||||
|
experimental/coroutine synopsis
|
||||||
|
|
||||||
|
// C++next
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
namespace experimental {
|
||||||
|
inline namespace coroutines_v1 {
|
||||||
|
|
||||||
|
// 18.11.1 coroutine traits
|
||||||
|
template <typename R, typename... ArgTypes>
|
||||||
|
class coroutine_traits;
|
||||||
|
// 18.11.2 coroutine handle
|
||||||
|
template <typename Promise = void>
|
||||||
|
class coroutine_handle;
|
||||||
|
// 18.11.2.7 comparison operators:
|
||||||
|
bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
bool operator!=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
bool operator<=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
bool operator>=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
bool operator>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
|
||||||
|
// 18.11.3 trivial awaitables
|
||||||
|
struct suspend_never;
|
||||||
|
struct suspend_always;
|
||||||
|
// 18.11.2.8 hash support:
|
||||||
|
template <class T> struct hash;
|
||||||
|
template <class P> struct hash<coroutine_handle<P>>;
|
||||||
|
|
||||||
|
} // namespace coroutines_v1
|
||||||
|
} // namespace experimental
|
||||||
|
} // namespace std
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <experimental/__config>
|
||||||
|
#include <new>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <functional>
|
||||||
|
#include <memory> // for hash<T*>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cassert>
|
||||||
|
#include <__debug>
|
||||||
|
|
||||||
|
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
|
||||||
|
#pragma GCC system_header
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __cpp_coroutines
|
||||||
|
# if defined(_LIBCPP_WARNING)
|
||||||
|
_LIBCPP_WARNING("<experimental/coroutine> cannot be used with this compiler")
|
||||||
|
# else
|
||||||
|
# warning <experimental/coroutine> cannot be used with this compiler
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES
|
||||||
|
|
||||||
|
template <class _Tp, class = void>
|
||||||
|
struct __coroutine_traits_sfinae {};
|
||||||
|
|
||||||
|
template <class _Tp>
|
||||||
|
struct __coroutine_traits_sfinae<
|
||||||
|
_Tp, typename __void_t<typename _Tp::promise_type>::type>
|
||||||
|
{
|
||||||
|
using promise_type = typename _Tp::promise_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _Ret, typename... _Args>
|
||||||
|
struct _LIBCPP_TEMPLATE_VIS coroutine_traits
|
||||||
|
: public __coroutine_traits_sfinae<_Ret>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename Promise = void>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS coroutine_handle;
|
||||||
|
|
||||||
|
#if defined(__cpp_coroutines)
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
|
||||||
|
public:
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
constexpr coroutine_handle() noexcept : __handle_(nullptr) {}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
constexpr coroutine_handle(nullptr_t) noexcept : __handle_(nullptr) {}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
coroutine_handle& operator=(nullptr_t) noexcept {
|
||||||
|
__handle_ = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
constexpr void* address() const noexcept { return __handle_; }
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
constexpr explicit operator bool() const noexcept { return __handle_; }
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void operator()() const { resume(); }
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void resume() const {
|
||||||
|
_LIBCPP_ASSERT(__is_suspended(),
|
||||||
|
"resume() can only be called on suspended coroutines");
|
||||||
|
_LIBCPP_ASSERT(!done(),
|
||||||
|
"resume() has undefined behavior when the coroutine is done");
|
||||||
|
__builtin_coro_resume(__handle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void destroy() const {
|
||||||
|
_LIBCPP_ASSERT(__is_suspended(),
|
||||||
|
"destroy() can only be called on suspended coroutines");
|
||||||
|
__builtin_coro_destroy(__handle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
bool done() const {
|
||||||
|
_LIBCPP_ASSERT(__is_suspended(),
|
||||||
|
"done() can only be called on suspended coroutines");
|
||||||
|
return __builtin_coro_done(__handle_);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
static coroutine_handle from_address(void* __addr) noexcept {
|
||||||
|
coroutine_handle __tmp;
|
||||||
|
__tmp.__handle_ = __addr;
|
||||||
|
return __tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool __is_suspended() const noexcept {
|
||||||
|
// FIXME actually implement a check for if the coro is suspended.
|
||||||
|
return __handle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class _PromiseT> friend class coroutine_handle;
|
||||||
|
void* __handle_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 18.11.2.7 comparison operators:
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return __x.address() == __y.address();
|
||||||
|
}
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return !(__x == __y);
|
||||||
|
}
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return less<void*>()(__x.address(), __y.address());
|
||||||
|
}
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return __y < __x;
|
||||||
|
}
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return !(__x > __y);
|
||||||
|
}
|
||||||
|
inline _LIBCPP_ALWAYS_INLINE
|
||||||
|
bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
|
||||||
|
return !(__x < __y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename _Promise>
|
||||||
|
class _LIBCPP_TEMPLATE_VIS coroutine_handle : public coroutine_handle<> {
|
||||||
|
using _Base = coroutine_handle<>;
|
||||||
|
public:
|
||||||
|
// 18.11.2.1 construct/reset
|
||||||
|
using coroutine_handle<>::coroutine_handle;
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
coroutine_handle& operator=(nullptr_t) noexcept {
|
||||||
|
_Base::operator=(nullptr);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_Promise& promise() {
|
||||||
|
return *reinterpret_cast<_Promise*>(
|
||||||
|
__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
_Promise const& promise() const {
|
||||||
|
return *reinterpret_cast<_Promise const*>(
|
||||||
|
__builtin_coro_promise(this->__handle_, alignof(_Promise), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
static coroutine_handle from_address(void* __addr) noexcept {
|
||||||
|
coroutine_handle __tmp;
|
||||||
|
__tmp.__handle_ = __addr;
|
||||||
|
return __tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
static coroutine_handle from_promise(_Promise& __promise) noexcept {
|
||||||
|
coroutine_handle __tmp;
|
||||||
|
__tmp.__handle_ = __builtin_coro_promise(_VSTD::addressof(__promise),
|
||||||
|
alignof(_Promise), true);
|
||||||
|
return __tmp;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // defined(__cpp_coroutines)
|
||||||
|
|
||||||
|
struct _LIBCPP_TYPE_VIS suspend_never {
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
bool await_ready() const noexcept { return true; }
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void await_suspend(coroutine_handle<>) const noexcept {}
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void await_resume() const noexcept {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _LIBCPP_TYPE_VIS suspend_always {
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
bool await_ready() const noexcept { return false; }
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void await_suspend(coroutine_handle<>) const noexcept {}
|
||||||
|
_LIBCPP_ALWAYS_INLINE
|
||||||
|
void await_resume() const noexcept {}
|
||||||
|
};
|
||||||
|
|
||||||
|
_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES
|
||||||
|
|
||||||
|
_LIBCPP_BEGIN_NAMESPACE_STD
|
||||||
|
|
||||||
|
template <class _Tp>
|
||||||
|
struct hash<_VSTD_CORO::coroutine_handle<_Tp> > {
|
||||||
|
using __arg_type = _VSTD_CORO::coroutine_handle<_Tp>;
|
||||||
|
_LIBCPP_INLINE_VISIBILITY
|
||||||
|
size_t operator()(__arg_type const& __v) const noexcept
|
||||||
|
{return hash<void*>{}(__v.address());}
|
||||||
|
};
|
||||||
|
|
||||||
|
_LIBCPP_END_NAMESPACE_STD
|
||||||
|
|
||||||
|
#endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */
|
||||||
@@ -501,6 +501,10 @@ module std [system] {
|
|||||||
header "experimental/chrono"
|
header "experimental/chrono"
|
||||||
export *
|
export *
|
||||||
}
|
}
|
||||||
|
module coroutine {
|
||||||
|
header "experimental/coroutine"
|
||||||
|
export *
|
||||||
|
}
|
||||||
module deque {
|
module deque {
|
||||||
header "experimental/deque"
|
header "experimental/deque"
|
||||||
export *
|
export *
|
||||||
|
|||||||
@@ -137,6 +137,9 @@
|
|||||||
#include <experimental/algorithm>
|
#include <experimental/algorithm>
|
||||||
#include <experimental/any>
|
#include <experimental/any>
|
||||||
#include <experimental/chrono>
|
#include <experimental/chrono>
|
||||||
|
#if defined(__cpp_coroutines)
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#endif
|
||||||
#include <experimental/deque>
|
#include <experimental/deque>
|
||||||
#include <experimental/dynarray>
|
#include <experimental/dynarray>
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
|
||||||
|
#ifndef _LIBCPP_VERSION
|
||||||
|
#error _LIBCPP_VERSION must be defined
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// constexpr explicit operator bool() const noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test() {
|
||||||
|
static_assert(std::is_nothrow_constructible<bool, C>::value, "");
|
||||||
|
static_assert(!std::is_convertible<C, bool>::value, "");
|
||||||
|
{
|
||||||
|
constexpr C c; ((void)c);
|
||||||
|
static_assert(bool(c) == false, "");
|
||||||
|
}
|
||||||
|
{ // null case
|
||||||
|
const C c = {}; ((void)c);
|
||||||
|
ASSERT_NOEXCEPT(bool(c));
|
||||||
|
if (c)
|
||||||
|
assert(false);
|
||||||
|
else
|
||||||
|
assert(true);
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
assert(bool(c) == false);
|
||||||
|
}
|
||||||
|
{ // non-null case
|
||||||
|
int dummy = 42;
|
||||||
|
C c = C::from_address(&dummy);
|
||||||
|
assert(c.address() == &dummy);
|
||||||
|
assert(bool(c) == true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test<coro::coroutine_handle<>>();
|
||||||
|
do_test<coro::coroutine_handle<int>>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// bool operator==(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
// bool operator!=(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test(uintptr_t LHSVal, uintptr_t RHSVal) {
|
||||||
|
const C LHS = C::from_address(reinterpret_cast<void*>(LHSVal));
|
||||||
|
const C RHS = C::from_address(reinterpret_cast<void*>(RHSVal));
|
||||||
|
const bool ExpectIsEqual = (LHSVal == RHSVal);
|
||||||
|
assert((LHS == RHS) == ExpectIsEqual);
|
||||||
|
assert((RHS == LHS) == ExpectIsEqual);
|
||||||
|
assert((LHS != RHS) == !ExpectIsEqual);
|
||||||
|
assert((RHS != LHS) == !ExpectIsEqual);
|
||||||
|
{
|
||||||
|
static_assert(noexcept(LHS == RHS), "");
|
||||||
|
static_assert(noexcept(LHS != RHS), "");
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS == RHS), bool);
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS != RHS), bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::pair<uintptr_t, uintptr_t> const TestCases[] = {
|
||||||
|
{0, 0},
|
||||||
|
{16, 16},
|
||||||
|
{0, 16},
|
||||||
|
{16, 0}
|
||||||
|
};
|
||||||
|
for (auto& TC : TestCases) {
|
||||||
|
do_test<coro::coroutine_handle<>>(TC.first, TC.second);
|
||||||
|
do_test<coro::coroutine_handle<int>>(TC.first, TC.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// bool operator<(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
// bool operator>(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
// bool operator>=(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
// bool operator<=(coroutine_handle<>, coroutine_handle<>) noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test(uintptr_t LHSVal, uintptr_t RHSVal) {
|
||||||
|
const C LHS = C::from_address(reinterpret_cast<void*>(LHSVal));
|
||||||
|
const C RHS = C::from_address(reinterpret_cast<void*>(RHSVal));
|
||||||
|
assert((LHS < RHS) == (LHSVal < RHSVal));
|
||||||
|
assert((RHS < LHS) == (RHSVal < LHSVal));
|
||||||
|
assert((LHS > RHS) == (LHSVal > RHSVal));
|
||||||
|
assert((RHS > LHS) == (RHSVal > LHSVal));
|
||||||
|
assert((LHS <= RHS) == (LHSVal <= RHSVal));
|
||||||
|
assert((RHS <= LHS) == (RHSVal <= LHSVal));
|
||||||
|
assert((LHS >= RHS) == (LHSVal >= RHSVal));
|
||||||
|
assert((RHS >= LHS) == (RHSVal >= LHSVal));
|
||||||
|
{
|
||||||
|
static_assert(noexcept(LHS < RHS), "");
|
||||||
|
static_assert(noexcept(LHS > RHS), "");
|
||||||
|
static_assert(noexcept(LHS <= RHS), "");
|
||||||
|
static_assert(noexcept(LHS >= RHS), "");
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS < RHS), bool);
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS > RHS), bool);
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS <= RHS), bool);
|
||||||
|
ASSERT_SAME_TYPE(decltype(LHS >= RHS), bool);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::pair<uintptr_t, uintptr_t> const TestCases[] = {
|
||||||
|
{0, 0},
|
||||||
|
{16, 16},
|
||||||
|
{0, 16},
|
||||||
|
{16, 0}
|
||||||
|
};
|
||||||
|
for (auto& TC : TestCases) {
|
||||||
|
do_test<coro::coroutine_handle<>>(TC.first, TC.second);
|
||||||
|
do_test<coro::coroutine_handle<int>>(TC.first, TC.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// bool done() const
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class Promise>
|
||||||
|
void do_test(coro::coroutine_handle<Promise> const& H) {
|
||||||
|
// FIXME Add a runtime test
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(decltype(H.done()), bool);
|
||||||
|
ASSERT_NOT_NOEXCEPT(H.done());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test(coro::coroutine_handle<>{});
|
||||||
|
do_test(coro::coroutine_handle<int>{});
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// coroutine_handle& operator=(nullptr_t) noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test() {
|
||||||
|
int dummy = 42;
|
||||||
|
void* dummy_h = &dummy;
|
||||||
|
{
|
||||||
|
C c; ((void)c);
|
||||||
|
static_assert(std::is_nothrow_assignable<C&, std::nullptr_t>::value, "");
|
||||||
|
static_assert(!std::is_assignable<C&, void*>::value, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
C c = C::from_address(dummy_h);
|
||||||
|
assert(c.address() == &dummy);
|
||||||
|
c = nullptr;
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
c = nullptr;
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
C c;
|
||||||
|
C& cr = (c = nullptr);
|
||||||
|
assert(&c == &cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test<coro::coroutine_handle<>>();
|
||||||
|
do_test<coro::coroutine_handle<int>>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// constexpr coroutine_handle() noexcept
|
||||||
|
// constexpr coroutine_handle(nullptr_t) noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test() {
|
||||||
|
{
|
||||||
|
constexpr C c;
|
||||||
|
static_assert(std::is_nothrow_default_constructible<C>::value, "");
|
||||||
|
static_assert(c.address() == nullptr, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
constexpr C c(nullptr);
|
||||||
|
static_assert(std::is_nothrow_constructible<C, std::nullptr_t>::value, "");
|
||||||
|
static_assert(c.address() == nullptr, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
C c;
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
C c(nullptr);
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test<coro::coroutine_handle<>>();
|
||||||
|
do_test<coro::coroutine_handle<int>>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// constexpr void* address() const noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test() {
|
||||||
|
{
|
||||||
|
constexpr C c; ((void)c);
|
||||||
|
static_assert(c.address() == nullptr, "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const C c = {}; ((void)c);
|
||||||
|
ASSERT_NOEXCEPT(c.address());
|
||||||
|
ASSERT_SAME_TYPE(decltype(c.address()), void*);
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int dummy = 42;
|
||||||
|
C c = C::from_address(&dummy);
|
||||||
|
assert(c.address() == &dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test<coro::coroutine_handle<>>();
|
||||||
|
do_test<coro::coroutine_handle<int>>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// static coroutine_handle from_address(void*) noexcept
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test() {
|
||||||
|
{
|
||||||
|
C c = C::from_address(nullptr);
|
||||||
|
static_assert(noexcept(C::from_address(nullptr)), "");
|
||||||
|
// FIXME: Should the return type not be 'C'?
|
||||||
|
static_assert(std::is_same<decltype(C::from_address(nullptr)), C>::value, "");
|
||||||
|
assert(c.address() == nullptr);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
int dummy = 42;
|
||||||
|
C c = C::from_address(&dummy);
|
||||||
|
assert(c.address() == &dummy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test<coro::coroutine_handle<>>();
|
||||||
|
do_test<coro::coroutine_handle<int>>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// namespace std {
|
||||||
|
// template <class P> struct hash<experimental::coroutine_handle<P>>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class C>
|
||||||
|
void do_test(uintptr_t LHSVal, uintptr_t RHSVal) {
|
||||||
|
const size_t ExpectLHS = std::hash<void*>{}(reinterpret_cast<void*>(LHSVal));
|
||||||
|
const size_t ExpectRHS = std::hash<void*>{}(reinterpret_cast<void*>(RHSVal));
|
||||||
|
const C LHS = C::from_address(reinterpret_cast<void*>(LHSVal));
|
||||||
|
const C RHS = C::from_address(reinterpret_cast<void*>(RHSVal));
|
||||||
|
const std::hash<C> h;
|
||||||
|
// FIXME: libc++'s implementation hash's the result of LHS.address(), so we
|
||||||
|
// expect that value. However this is not required.
|
||||||
|
assert(h(LHS) == ExpectLHS);
|
||||||
|
assert(h(RHS) == ExpectRHS);
|
||||||
|
assert((h(LHS) == h(RHS)) == (LHSVal == RHSVal));
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(decltype(h(LHS)), size_t);
|
||||||
|
ASSERT_NOEXCEPT(std::hash<C>{}(LHS));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
std::pair<uintptr_t, uintptr_t> const TestCases[] = {
|
||||||
|
{0, 0},
|
||||||
|
{0, 8},
|
||||||
|
{8, 8},
|
||||||
|
{8, 16}
|
||||||
|
};
|
||||||
|
for (auto& TC : TestCases) {
|
||||||
|
do_test<coro::coroutine_handle<>>(TC.first, TC.second);
|
||||||
|
do_test<coro::coroutine_handle<int>>(TC.first, TC.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise>
|
||||||
|
// struct coroutine_handle<Promise>;
|
||||||
|
|
||||||
|
// Promise& promise()
|
||||||
|
// Promise const& promise() const
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class Promise>
|
||||||
|
void do_test(coro::coroutine_handle<Promise>&& H) {
|
||||||
|
|
||||||
|
// FIXME Add a runtime test
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(decltype(H.promise()), Promise&);
|
||||||
|
ASSERT_NOT_NOEXCEPT(H.promise());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto const& CH = H;
|
||||||
|
ASSERT_SAME_TYPE(decltype(CH.promise()), Promise const&);
|
||||||
|
ASSERT_NOT_NOEXCEPT(CH.promise());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test(coro::coroutine_handle<int>{});
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// void destroy() const
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class Promise>
|
||||||
|
void do_test(coro::coroutine_handle<Promise> const& H) {
|
||||||
|
// FIXME Add a runtime test
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(decltype(H.destroy()), void);
|
||||||
|
ASSERT_NOT_NOEXCEPT(H.destroy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test(coro::coroutine_handle<>{});
|
||||||
|
do_test(coro::coroutine_handle<int>{});
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// template <class Promise = void>
|
||||||
|
// struct coroutine_handle;
|
||||||
|
|
||||||
|
// void operator()() const
|
||||||
|
// void resume() const
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <memory>
|
||||||
|
#include <utility>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class Promise>
|
||||||
|
void do_test(coro::coroutine_handle<Promise> const& H) {
|
||||||
|
// FIXME Add a runtime test
|
||||||
|
{
|
||||||
|
ASSERT_SAME_TYPE(decltype(H.resume()), void);
|
||||||
|
ASSERT_SAME_TYPE(decltype(H()), void);
|
||||||
|
ASSERT_NOT_NOEXCEPT(H.resume());
|
||||||
|
ASSERT_NOT_NOEXCEPT(H());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
do_test(coro::coroutine_handle<>{});
|
||||||
|
do_test(coro::coroutine_handle<int>{});
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
using promise_type = A*;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {};
|
||||||
|
struct C {};
|
||||||
|
|
||||||
|
namespace std { namespace experimental {
|
||||||
|
template <>
|
||||||
|
struct coroutine_traits<::A, int> {
|
||||||
|
using promise_type = int*;
|
||||||
|
};
|
||||||
|
template <class ...Args>
|
||||||
|
struct coroutine_traits<::B, Args...> {
|
||||||
|
using promise_type = B*;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct coroutine_traits<::C> {
|
||||||
|
using promise_type = void;
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
|
||||||
|
template <class Expect, class T, class ...Args>
|
||||||
|
void check_type() {
|
||||||
|
using P = typename coro::coroutine_traits<T, Args...>::promise_type ;
|
||||||
|
static_assert(std::is_same<P, Expect>::value, "");
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
check_type<A*, A>();
|
||||||
|
check_type<int*, A, int>();
|
||||||
|
check_type<B*, B>();
|
||||||
|
check_type<void, C>();
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
template <class T, class = typename T::promise_type>
|
||||||
|
constexpr bool has_promise_type(int) { return true; }
|
||||||
|
template <class>
|
||||||
|
constexpr bool has_promise_type(long) { return false; }
|
||||||
|
template <class T>
|
||||||
|
constexpr bool has_promise_type() { return has_promise_type<T>(0); }
|
||||||
|
|
||||||
|
struct A {
|
||||||
|
using promise_type = A*;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B {};
|
||||||
|
struct C {};
|
||||||
|
struct D {
|
||||||
|
private:
|
||||||
|
using promise_type = void;
|
||||||
|
};
|
||||||
|
struct E {};
|
||||||
|
|
||||||
|
namespace std { namespace experimental {
|
||||||
|
template <>
|
||||||
|
struct coroutine_traits<::A, int> {
|
||||||
|
using promise_type = int*;
|
||||||
|
};
|
||||||
|
template <class ...Args>
|
||||||
|
struct coroutine_traits<::B, Args...> {
|
||||||
|
using promise_type = B*;
|
||||||
|
};
|
||||||
|
template <>
|
||||||
|
struct coroutine_traits<::C> {
|
||||||
|
using promise_type = void;
|
||||||
|
};
|
||||||
|
}}
|
||||||
|
|
||||||
|
template <class Expect, class T, class ...Args>
|
||||||
|
void check_type() {
|
||||||
|
using Traits = coro::coroutine_traits<T, Args...>;
|
||||||
|
static_assert(has_promise_type<Traits>(), "");
|
||||||
|
static_assert(std::is_same<typename Traits::promise_type, Expect>::value, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class ...Args>
|
||||||
|
void check_no_type() {
|
||||||
|
using Traits = coro::coroutine_traits<T, Args...>;
|
||||||
|
static_assert(!has_promise_type<Traits>(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
check_type<A*, A>();
|
||||||
|
check_type<int*, A, int>();
|
||||||
|
check_type<B*, B>();
|
||||||
|
check_type<void, C>();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
check_no_type<D>();
|
||||||
|
check_no_type<E>();
|
||||||
|
check_no_type<C, int>();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
using SuspendT = std::experimental::coroutines_v1::suspend_always;
|
||||||
|
|
||||||
|
TEST_SAFE_STATIC SuspendT safe_sa;
|
||||||
|
constexpr SuspendT constexpr_sa;
|
||||||
|
|
||||||
|
constexpr bool check_suspend_constexpr() {
|
||||||
|
SuspendT s{};
|
||||||
|
const SuspendT scopy(s); ((void)scopy);
|
||||||
|
SuspendT smove(std::move(s)); ((void)smove);
|
||||||
|
s = scopy;
|
||||||
|
s = std::move(smove);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using H = coro::coroutine_handle<>;
|
||||||
|
using S = SuspendT;
|
||||||
|
H h{};
|
||||||
|
S s{};
|
||||||
|
S const& cs = s;
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_ready()), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_ready()), bool>::value, "");
|
||||||
|
assert(s.await_ready() == false);
|
||||||
|
assert(cs.await_ready() == false);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_suspend(h)), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_suspend(h)), void>::value, "");
|
||||||
|
s.await_suspend(h);
|
||||||
|
cs.await_suspend(h);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_resume()), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_resume()), void>::value, "");
|
||||||
|
s.await_resume();
|
||||||
|
cs.await_resume();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static_assert(std::is_nothrow_default_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_copy_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_move_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_copy_assignable<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_move_assignable<S>::value, "");
|
||||||
|
static_assert(std::is_trivially_copyable<S>::value, "");
|
||||||
|
static_assert(check_suspend_constexpr(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "test_macros.h"
|
||||||
|
|
||||||
|
namespace coro = std::experimental;
|
||||||
|
|
||||||
|
// Test that the type is in the correct namespace
|
||||||
|
using SuspendT = std::experimental::coroutines_v1::suspend_never;
|
||||||
|
|
||||||
|
TEST_SAFE_STATIC SuspendT safe_sn;
|
||||||
|
constexpr SuspendT constexpr_sn;
|
||||||
|
|
||||||
|
constexpr bool check_suspend_constexpr() {
|
||||||
|
SuspendT s{};
|
||||||
|
const SuspendT scopy(s); ((void)scopy);
|
||||||
|
SuspendT smove(std::move(s)); ((void)smove);
|
||||||
|
s = scopy;
|
||||||
|
s = std::move(smove);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
using H = coro::coroutine_handle<>;
|
||||||
|
using S = SuspendT;
|
||||||
|
H h{};
|
||||||
|
S s{};
|
||||||
|
S const& cs = s;
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_ready()), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_ready()), bool>::value, "");
|
||||||
|
assert(s.await_ready() == true);
|
||||||
|
assert(cs.await_ready() == true);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_suspend(h)), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_suspend(h)), void>::value, "");
|
||||||
|
s.await_suspend(h);
|
||||||
|
cs.await_suspend(h);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
LIBCPP_STATIC_ASSERT(noexcept(s.await_resume()), "");
|
||||||
|
static_assert(std::is_same<decltype(s.await_resume()), void>::value, "");
|
||||||
|
s.await_resume();
|
||||||
|
cs.await_resume();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
static_assert(std::is_nothrow_default_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_copy_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_move_constructible<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_copy_assignable<S>::value, "");
|
||||||
|
static_assert(std::is_nothrow_move_assignable<S>::value, "");
|
||||||
|
static_assert(std::is_trivially_copyable<S>::value, "");
|
||||||
|
static_assert(check_suspend_constexpr(), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
// -*- C++ -*-
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is dual licensed under the MIT and the University of Illinois Open
|
||||||
|
// Source Licenses. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
// UNSUPPORTED: c++98, c++03, c++11
|
||||||
|
// REQUIRES: fcoroutines-ts
|
||||||
|
|
||||||
|
// RUN: %build -fcoroutines-ts
|
||||||
|
// RUN: %run
|
||||||
|
|
||||||
|
// <experimental/coroutine>
|
||||||
|
|
||||||
|
// Test that <experimental/coroutine> includes <new>
|
||||||
|
|
||||||
|
#include <experimental/coroutine>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(){
|
||||||
|
// std::nothrow is not implicitly defined by the compiler when the include is
|
||||||
|
// missing, unlike other parts of <new>. Therefore we use std::nothrow to
|
||||||
|
// test for #include <new>
|
||||||
|
(void)std::nothrow;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -154,6 +154,12 @@
|
|||||||
#define TEST_NORETURN [[noreturn]]
|
#define TEST_NORETURN [[noreturn]]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(_LIBCPP_SAFE_STATIC)
|
||||||
|
#define TEST_SAFE_STATIC _LIBCPP_SAFE_STATIC
|
||||||
|
#else
|
||||||
|
#define TEST_SAFE_STATIC
|
||||||
|
#endif
|
||||||
|
|
||||||
#if TEST_STD_VER < 11
|
#if TEST_STD_VER < 11
|
||||||
#define ASSERT_NOEXCEPT(...)
|
#define ASSERT_NOEXCEPT(...)
|
||||||
#define ASSERT_NOT_NOEXCEPT(...)
|
#define ASSERT_NOT_NOEXCEPT(...)
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ class Configuration(object):
|
|||||||
self.configure_sanitizer()
|
self.configure_sanitizer()
|
||||||
self.configure_coverage()
|
self.configure_coverage()
|
||||||
self.configure_modules()
|
self.configure_modules()
|
||||||
|
self.configure_coroutines()
|
||||||
self.configure_substitutions()
|
self.configure_substitutions()
|
||||||
self.configure_features()
|
self.configure_features()
|
||||||
|
|
||||||
@@ -954,6 +955,10 @@ class Configuration(object):
|
|||||||
self.cxx.flags += ['-g', '--coverage']
|
self.cxx.flags += ['-g', '--coverage']
|
||||||
self.cxx.compile_flags += ['-O0']
|
self.cxx.compile_flags += ['-O0']
|
||||||
|
|
||||||
|
def configure_coroutines(self):
|
||||||
|
if self.cxx.hasCompileFlag('-fcoroutines-ts'):
|
||||||
|
self.config.available_features.add('fcoroutines-ts')
|
||||||
|
|
||||||
def configure_modules(self):
|
def configure_modules(self):
|
||||||
modules_flags = ['-fmodules']
|
modules_flags = ['-fmodules']
|
||||||
if platform.system() != 'Darwin':
|
if platform.system() != 'Darwin':
|
||||||
|
|||||||
Reference in New Issue
Block a user