Vendor import of libc++ trunk r304149:
https://llvm.org/svn/llvm-project/libcxx/trunk@304149
This commit is contained in:
parent
d1bd27794d
commit
b276b1db48
@ -452,6 +452,11 @@ add_compile_flags_if_supported(-nostdinc++)
|
||||
# the dylib when get ODR used by another function.
|
||||
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
|
||||
# library.
|
||||
add_definitions(-D_LIBCPP_BUILDING_LIBRARY)
|
||||
|
@ -41,7 +41,15 @@ if (LIBCXX_SUPPORTS_NODEFAULTLIBS_FLAG)
|
||||
if (MINGW)
|
||||
# Mingw64 requires quite a few "C" runtime libraries in order for basic
|
||||
# programs to link successfully with -nodefaultlibs.
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES mingw32 gcc gcc_eh mingwex msvcrt gcc)
|
||||
if (LIBCXX_USE_COMPILER_RT)
|
||||
set(MINGW_RUNTIME ${LIBCXX_BUILTINS_LIBRARY})
|
||||
else ()
|
||||
set(MINGW_RUNTIME gcc_s gcc)
|
||||
endif()
|
||||
set(MINGW_LIBRARIES mingw32 ${MINGW_RUNTIME} moldname mingwex msvcrt advapi32
|
||||
shell32 user32 kernel32 mingw32 ${MINGW_RUNTIME}
|
||||
moldname mingwex msvcrt)
|
||||
list(APPEND CMAKE_REQUIRED_LIBRARIES ${MINGW_LIBRARIES})
|
||||
endif()
|
||||
if (CMAKE_C_FLAGS MATCHES -fsanitize OR CMAKE_CXX_FLAGS MATCHES -fsanitize)
|
||||
set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -fno-sanitize=all")
|
||||
|
@ -1126,6 +1126,10 @@ _LIBCPP_FUNC_VIS extern "C" void __sanitizer_annotate_contiguous_container(
|
||||
# define _LIBCPP_HAS_NO_IS_AGGREGATE
|
||||
#endif
|
||||
|
||||
#if !defined(__cpp_coroutines) || __cpp_coroutines < 201703L
|
||||
# define _LIBCPP_HAS_NO_COROUTINES
|
||||
#endif
|
||||
|
||||
#endif // __cplusplus
|
||||
|
||||
// Decide whether to use availability macros.
|
||||
|
@ -27,7 +27,7 @@
|
||||
# include <pthread.h>
|
||||
# include <sched.h>
|
||||
#elif defined(_LIBCPP_HAS_THREAD_API_WIN32)
|
||||
#include <Windows.h>
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
#include <fibersapi.h>
|
||||
#include <__undef_min_max>
|
||||
|
@ -35,6 +35,9 @@ template <class InputIterator, class Function>
|
||||
Function
|
||||
for_each(InputIterator first, InputIterator last, Function f);
|
||||
|
||||
template<class InputIterator, class Size, class Function>
|
||||
InputIterator for_each_n(InputIterator first, Size n, Function f); // C++17
|
||||
|
||||
template <class InputIterator, class T>
|
||||
InputIterator
|
||||
find(InputIterator first, InputIterator last, const T& value);
|
||||
@ -961,6 +964,26 @@ for_each(_InputIterator __first, _InputIterator __last, _Function __f)
|
||||
return __f;
|
||||
}
|
||||
|
||||
#if _LIBCPP_STD_VER > 14
|
||||
// for_each_n
|
||||
|
||||
template <class _InputIterator, class _Size, class _Function>
|
||||
inline _LIBCPP_INLINE_VISIBILITY
|
||||
_InputIterator
|
||||
for_each_n(_InputIterator __first, _Size __orig_n, _Function __f)
|
||||
{
|
||||
typedef decltype(__convert_to_integral(__orig_n)) _IntegralSize;
|
||||
_IntegralSize __n = __orig_n;
|
||||
while (__n > 0)
|
||||
{
|
||||
__f(*__first);
|
||||
++__first;
|
||||
--__n;
|
||||
}
|
||||
return __first;
|
||||
}
|
||||
#endif
|
||||
|
||||
// find
|
||||
|
||||
template <class _InputIterator, class _Tp>
|
||||
|
@ -44,6 +44,13 @@
|
||||
#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM \
|
||||
} } _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
|
||||
|
||||
|
270
include/experimental/coroutine
Normal file
270
include/experimental/coroutine
Normal file
@ -0,0 +1,270 @@
|
||||
// -*- 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
|
||||
|
||||
#ifdef _LIBCPP_HAS_NO_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
|
||||
|
||||
#ifndef _LIBCPP_HAS_NO_COROUTINES
|
||||
|
||||
_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;
|
||||
|
||||
template <>
|
||||
class _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
|
||||
public:
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_CONSTEXPR coroutine_handle() _NOEXCEPT : __handle_(nullptr) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_CONSTEXPR coroutine_handle(nullptr_t) _NOEXCEPT : __handle_(nullptr) {}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
coroutine_handle& operator=(nullptr_t) _NOEXCEPT {
|
||||
__handle_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_CONSTEXPR void* address() const _NOEXCEPT { return __handle_; }
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
_LIBCPP_CONSTEXPR explicit operator bool() const _NOEXCEPT { return __handle_; }
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
void operator()() { resume(); }
|
||||
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
void resume() {
|
||||
_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() {
|
||||
_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:
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
// 18.11.2.1 construct/reset
|
||||
using coroutine_handle<>::coroutine_handle;
|
||||
#else
|
||||
_LIBCPP_ALWAYS_INLINE coroutine_handle() _NOEXCEPT : _Base() {}
|
||||
_LIBCPP_ALWAYS_INLINE coroutine_handle(nullptr_t) _NOEXCEPT : _Base(nullptr) {}
|
||||
#endif
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
coroutine_handle& operator=(nullptr_t) _NOEXCEPT {
|
||||
_Base::operator=(nullptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_Promise& promise() const {
|
||||
return *reinterpret_cast<_Promise*>(
|
||||
__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;
|
||||
}
|
||||
|
||||
// NOTE: this overload isn't required by the standard but is needed so
|
||||
// the deleted _Promise* overload doesn't make from_address(nullptr)
|
||||
// ambiguous.
|
||||
// FIXME: should from_address work with nullptr?
|
||||
_LIBCPP_ALWAYS_INLINE
|
||||
static coroutine_handle from_address(nullptr_t) _NOEXCEPT {
|
||||
return {};
|
||||
}
|
||||
|
||||
// from_address cannot be used with the coroutines promise type.
|
||||
static coroutine_handle from_address(_Promise*) = delete;
|
||||
|
||||
_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;
|
||||
}
|
||||
};
|
||||
|
||||
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 // !defined(_LIBCPP_HAS_NO_COROUTINES)
|
||||
|
||||
#endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */
|
@ -990,7 +990,6 @@ public:
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY char_type operator*() const
|
||||
{return static_cast<char_type>(__sbuf_->sgetc());}
|
||||
_LIBCPP_INLINE_VISIBILITY char_type* operator->() const {return nullptr;}
|
||||
_LIBCPP_INLINE_VISIBILITY istreambuf_iterator& operator++()
|
||||
{
|
||||
__sbuf_->sbumpc();
|
||||
|
@ -2251,6 +2251,8 @@ void swap(__compressed_pair<_T1, _T2>& __x, __compressed_pair<_T1, _T2>& __y)
|
||||
|
||||
template <class _Tp>
|
||||
struct _LIBCPP_TEMPLATE_VIS default_delete {
|
||||
static_assert(!is_function<_Tp>::value,
|
||||
"default_delete cannot be instantiated for function types");
|
||||
#ifndef _LIBCPP_CXX03_LANG
|
||||
_LIBCPP_INLINE_VISIBILITY constexpr default_delete() noexcept = default;
|
||||
#else
|
||||
@ -3653,6 +3655,18 @@ __shared_ptr_emplace<_Tp, _Alloc>::__on_zero_shared_weak() _NOEXCEPT
|
||||
__a.deallocate(_PTraits::pointer_to(*this), 1);
|
||||
}
|
||||
|
||||
struct __shared_ptr_dummy_rebind_allocator_type;
|
||||
template <>
|
||||
class _LIBCPP_TEMPLATE_VIS allocator<__shared_ptr_dummy_rebind_allocator_type>
|
||||
{
|
||||
public:
|
||||
template <class _Other>
|
||||
struct rebind
|
||||
{
|
||||
typedef allocator<_Other> other;
|
||||
};
|
||||
};
|
||||
|
||||
template<class _Tp> class _LIBCPP_TEMPLATE_VIS enable_shared_from_this;
|
||||
|
||||
template<class _Tp>
|
||||
@ -3921,6 +3935,17 @@ public:
|
||||
#endif // _LIBCPP_HAS_NO_VARIADICS
|
||||
|
||||
private:
|
||||
template <class _Yp, bool = is_function<_Yp>::value>
|
||||
struct __shared_ptr_default_allocator
|
||||
{
|
||||
typedef allocator<_Yp> type;
|
||||
};
|
||||
|
||||
template <class _Yp>
|
||||
struct __shared_ptr_default_allocator<_Yp, true>
|
||||
{
|
||||
typedef allocator<__shared_ptr_dummy_rebind_allocator_type> type;
|
||||
};
|
||||
|
||||
template <class _Yp, class _OrigPtr>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
@ -3939,8 +3964,7 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
void __enable_weak_this(const volatile void*, const volatile void*) _NOEXCEPT {}
|
||||
_LIBCPP_INLINE_VISIBILITY void __enable_weak_this(...) _NOEXCEPT {}
|
||||
|
||||
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS shared_ptr;
|
||||
template <class _Up> friend class _LIBCPP_TEMPLATE_VIS weak_ptr;
|
||||
@ -3972,8 +3996,9 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p,
|
||||
: __ptr_(__p)
|
||||
{
|
||||
unique_ptr<_Yp> __hold(__p);
|
||||
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, allocator<_Yp> > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), allocator<_Yp>());
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<_Yp*, default_delete<_Yp>, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, default_delete<_Yp>(), _AllocT());
|
||||
__hold.release();
|
||||
__enable_weak_this(__p, __p);
|
||||
}
|
||||
@ -3988,8 +4013,9 @@ shared_ptr<_Tp>::shared_ptr(_Yp* __p, _Dp __d,
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, __d, allocator<_Yp>());
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, __d, _AllocT());
|
||||
__enable_weak_this(__p, __p);
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
@ -4010,8 +4036,9 @@ shared_ptr<_Tp>::shared_ptr(nullptr_t __p, _Dp __d)
|
||||
try
|
||||
{
|
||||
#endif // _LIBCPP_NO_EXCEPTIONS
|
||||
typedef __shared_ptr_pointer<nullptr_t, _Dp, allocator<_Tp> > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, __d, allocator<_Tp>());
|
||||
typedef typename __shared_ptr_default_allocator<_Tp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<nullptr_t, _Dp, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__p, __d, _AllocT());
|
||||
#ifndef _LIBCPP_NO_EXCEPTIONS
|
||||
}
|
||||
catch (...)
|
||||
@ -4179,8 +4206,9 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp> __r,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
typedef __shared_ptr_pointer<_Yp*, _Dp, allocator<_Yp> > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), allocator<_Yp>());
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<_Yp*, _Dp, _AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__r.get(), __r.get_deleter(), _AllocT());
|
||||
__enable_weak_this(__r.get(), __r.get());
|
||||
}
|
||||
__r.release();
|
||||
@ -4208,10 +4236,11 @@ shared_ptr<_Tp>::shared_ptr(unique_ptr<_Yp, _Dp> __r,
|
||||
else
|
||||
#endif
|
||||
{
|
||||
typedef typename __shared_ptr_default_allocator<_Yp>::type _AllocT;
|
||||
typedef __shared_ptr_pointer<_Yp*,
|
||||
reference_wrapper<typename remove_reference<_Dp>::type>,
|
||||
allocator<_Yp> > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), allocator<_Yp>());
|
||||
_AllocT > _CntrlBlk;
|
||||
__cntrl_ = new _CntrlBlk(__r.get(), ref(__r.get_deleter()), _AllocT());
|
||||
__enable_weak_this(__r.get(), __r.get());
|
||||
}
|
||||
__r.release();
|
||||
|
@ -500,6 +500,10 @@ module std [system] {
|
||||
module chrono {
|
||||
header "experimental/chrono"
|
||||
export *
|
||||
}
|
||||
module coroutine {
|
||||
header "experimental/coroutine"
|
||||
export *
|
||||
}
|
||||
module deque {
|
||||
header "experimental/deque"
|
||||
|
@ -242,14 +242,11 @@ endif()
|
||||
if (LIBCXX_ENABLE_STATIC)
|
||||
add_library(cxx_static STATIC $<TARGET_OBJECTS:cxx_objects>)
|
||||
target_link_libraries(cxx_static ${LIBCXX_LIBRARIES})
|
||||
set(STATIC_OUTPUT_NAME "c++")
|
||||
if (WIN32)
|
||||
set(STATIC_OUTPUT_NAME "libc++")
|
||||
endif()
|
||||
set(CMAKE_STATIC_LIBRARY_PREFIX "lib")
|
||||
set_target_properties(cxx_static
|
||||
PROPERTIES
|
||||
LINK_FLAGS "${LIBCXX_LINK_FLAGS}"
|
||||
OUTPUT_NAME "${STATIC_OUTPUT_NAME}"
|
||||
OUTPUT_NAME "c++"
|
||||
)
|
||||
|
||||
list(APPEND LIBCXX_TARGETS "cxx_static")
|
||||
|
@ -137,6 +137,9 @@
|
||||
#include <experimental/algorithm>
|
||||
#include <experimental/any>
|
||||
#include <experimental/chrono>
|
||||
#if defined(__cpp_coroutines)
|
||||
#include <experimental/coroutine>
|
||||
#endif
|
||||
#include <experimental/deque>
|
||||
#include <experimental/dynarray>
|
||||
#include <experimental/filesystem>
|
||||
|
@ -0,0 +1,59 @@
|
||||
// -*- 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// REQUIRES: fcoroutines-ts
|
||||
|
||||
// RUN: %build -fcoroutines-ts
|
||||
// RUN: %run
|
||||
|
||||
// A simple "breathing" test that checks that <experimental/coroutine>
|
||||
// can be parsed and used in all dialects, including C++03 in order to match
|
||||
// Clang's behavior.
|
||||
|
||||
#include <experimental/coroutine>
|
||||
|
||||
namespace coro = std::experimental::coroutines_v1;
|
||||
|
||||
coro::suspend_always sa;
|
||||
coro::suspend_never sn;
|
||||
|
||||
struct MyFuture {
|
||||
struct promise_type {
|
||||
typedef coro::coroutine_handle<promise_type> HandleT;
|
||||
coro::suspend_never initial_suspend() { return sn; }
|
||||
coro::suspend_always final_suspend() { return sa; }
|
||||
coro::suspend_never yield_value(int) { return sn; }
|
||||
MyFuture get_return_object() {
|
||||
MyFuture f(HandleT::from_promise(*this));
|
||||
return f;
|
||||
}
|
||||
void return_void() {}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
typedef promise_type::HandleT HandleT;
|
||||
MyFuture() : p() {}
|
||||
MyFuture(HandleT h) : p(h) {}
|
||||
|
||||
coro::coroutine_handle<promise_type> p;
|
||||
};
|
||||
|
||||
MyFuture test_coro() {
|
||||
co_await sn;
|
||||
co_yield 42;
|
||||
co_return;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
MyFuture f = test_coro();
|
||||
while (!f.p.done())
|
||||
f.p.resume();
|
||||
f.p.destroy();
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
// -*- C++ -*-
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
@ -7,22 +8,18 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <iterator>
|
||||
// UNSUPPORTED: c++98, c++03, c++11
|
||||
// REQUIRES: fcoroutines-ts
|
||||
|
||||
// istreambuf_iterator
|
||||
// RUN: %build -fcoroutines-ts
|
||||
// RUN: %run
|
||||
|
||||
// pointer operator->() const;
|
||||
#include <experimental/coroutine>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <streambuf>
|
||||
#ifndef _LIBCPP_VERSION
|
||||
#error _LIBCPP_VERSION must be defined
|
||||
#endif
|
||||
|
||||
typedef char C;
|
||||
int main ()
|
||||
int main()
|
||||
{
|
||||
std::istringstream s("filename");
|
||||
std::istreambuf_iterator<char> i(s);
|
||||
|
||||
(*i).~C(); // This is well-formed...
|
||||
i->~C(); // ... so this should be supported!
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
// UNSUPPORTED: c++98, c++03
|
||||
|
||||
#include <memory>
|
||||
|
||||
template <int> struct Tag {};
|
||||
|
||||
template <int ID>
|
||||
using SPtr = std::shared_ptr<void(Tag<ID>)>;
|
||||
|
||||
template <int ID>
|
||||
using FnType = void(Tag<ID>);
|
||||
|
||||
template <int ID>
|
||||
void TestFn(Tag<ID>) {}
|
||||
|
||||
template <int ID>
|
||||
FnType<ID>* getFn() {
|
||||
return &TestFn<ID>;
|
||||
}
|
||||
|
||||
struct Deleter {
|
||||
template <class Tp>
|
||||
void operator()(Tp) const {
|
||||
using RawT = typename std::remove_pointer<Tp>::type;
|
||||
static_assert(std::is_function<RawT>::value ||
|
||||
std::is_same<typename std::remove_cv<RawT>::type,
|
||||
std::nullptr_t>::value,
|
||||
"");
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
{
|
||||
SPtr<0> s; // OK
|
||||
SPtr<1> s1(nullptr); // OK
|
||||
SPtr<2> s2(getFn<2>(), Deleter{}); // OK
|
||||
SPtr<3> s3(nullptr, Deleter{}); // OK
|
||||
}
|
||||
// expected-error@memory:* 2 {{static_assert failed "default_delete cannot be instantiated for function types"}}
|
||||
{
|
||||
SPtr<4> s4(getFn<4>()); // expected-note {{requested here}}
|
||||
SPtr<5> s5(getFn<5>(), std::default_delete<FnType<5>>{}); // expected-note {{requested here}}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// <algorithm>
|
||||
// UNSUPPORTED: c++98, c++03, c++11, c++14
|
||||
|
||||
// template<class InputIterator, class Size, class Function>
|
||||
// InputIterator for_each_n(InputIterator first, Size n, Function f);
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_iterators.h"
|
||||
|
||||
struct for_each_test
|
||||
{
|
||||
for_each_test(int c) : count(c) {}
|
||||
int count;
|
||||
void operator()(int& i) {++i; ++count;}
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
typedef input_iterator<int*> Iter;
|
||||
int ia[] = {0, 1, 2, 3, 4, 5};
|
||||
const unsigned s = sizeof(ia)/sizeof(ia[0]);
|
||||
|
||||
{
|
||||
auto f = for_each_test(0);
|
||||
Iter it = std::for_each_n(Iter(ia), 0, std::ref(f));
|
||||
assert(it == Iter(ia));
|
||||
assert(f.count == 0);
|
||||
}
|
||||
|
||||
{
|
||||
auto f = for_each_test(0);
|
||||
Iter it = std::for_each_n(Iter(ia), s, std::ref(f));
|
||||
|
||||
assert(it == Iter(ia+s));
|
||||
assert(f.count == s);
|
||||
for (unsigned i = 0; i < s; ++i)
|
||||
assert(ia[i] == static_cast<int>(i+1));
|
||||
}
|
||||
|
||||
{
|
||||
auto f = for_each_test(0);
|
||||
Iter it = std::for_each_n(Iter(ia), 1, std::ref(f));
|
||||
|
||||
assert(it == Iter(ia+1));
|
||||
assert(f.count == 1);
|
||||
for (unsigned i = 0; i < 1; ++i)
|
||||
assert(ia[i] == static_cast<int>(i+2));
|
||||
}
|
||||
}
|
@ -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
|
||||
char dummy = 42;
|
||||
C c = C::from_address((void*)&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);
|
||||
}
|
||||
{
|
||||
char dummy = 42;
|
||||
C c = C::from_address((void*)&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);
|
||||
}
|
||||
{
|
||||
char dummy = 42;
|
||||
C c = C::from_address((void*)&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,53 @@
|
||||
// -*- 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() 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&);
|
||||
LIBCPP_ASSERT_NOT_NOEXCEPT(H.promise());
|
||||
}
|
||||
{
|
||||
auto const& CH = H;
|
||||
ASSERT_SAME_TYPE(decltype(CH.promise()), Promise&);
|
||||
LIBCPP_ASSERT_NOT_NOEXCEPT(CH.promise());
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
do_test(coro::coroutine_handle<int>{});
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
// -*- 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()
|
||||
|
||||
#include <experimental/coroutine>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace coro = std::experimental;
|
||||
|
||||
template <class H>
|
||||
auto has_destroy_imp(H&& h, int) -> decltype(h.destroy(), std::true_type{});
|
||||
template <class H>
|
||||
auto has_destroy_imp(H&&, long) -> std::false_type;
|
||||
|
||||
template <class H>
|
||||
constexpr bool has_destroy() {
|
||||
return decltype(has_destroy_imp(std::declval<H>(), 0))::value;
|
||||
}
|
||||
|
||||
template <class Promise>
|
||||
void do_test(coro::coroutine_handle<Promise>&& H) {
|
||||
using HType = coro::coroutine_handle<Promise>;
|
||||
// FIXME Add a runtime test
|
||||
{
|
||||
ASSERT_SAME_TYPE(decltype(H.destroy()), void);
|
||||
LIBCPP_ASSERT_NOT_NOEXCEPT(H.destroy());
|
||||
static_assert(has_destroy<HType&>(), "");
|
||||
static_assert(has_destroy<HType&&>(), "");
|
||||
}
|
||||
{
|
||||
static_assert(!has_destroy<HType const&>(), "");
|
||||
static_assert(!has_destroy<HType const&&>(), "");
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
do_test(coro::coroutine_handle<>{});
|
||||
do_test(coro::coroutine_handle<int>{});
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
// -*- 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()()
|
||||
// void resume()
|
||||
|
||||
#include <experimental/coroutine>
|
||||
#include <type_traits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
namespace coro = std::experimental;
|
||||
|
||||
|
||||
template <class H>
|
||||
auto has_resume_imp(H&& h, int) -> decltype(h.resume(), std::true_type{});
|
||||
template <class H>
|
||||
auto has_resume_imp(H&&, long) -> std::false_type;
|
||||
|
||||
template <class H>
|
||||
constexpr bool has_resume() {
|
||||
return decltype(has_resume_imp(std::declval<H>(), 0))::value;
|
||||
}
|
||||
|
||||
|
||||
template <class H>
|
||||
auto has_call_operator_imp(H&& h, int) -> decltype(h(), std::true_type{});
|
||||
template <class H>
|
||||
auto has_call_operator_imp(H&&, long) -> std::false_type;
|
||||
|
||||
template <class H>
|
||||
constexpr bool has_call_operator() {
|
||||
return decltype(has_call_operator_imp(std::declval<H>(), 0))::value;
|
||||
}
|
||||
|
||||
template <class Promise>
|
||||
void do_test(coro::coroutine_handle<Promise>&& H) {
|
||||
using HType = coro::coroutine_handle<Promise>;
|
||||
// FIXME Add a runtime test
|
||||
{
|
||||
ASSERT_SAME_TYPE(decltype(H.resume()), void);
|
||||
ASSERT_SAME_TYPE(decltype(H()), void);
|
||||
LIBCPP_ASSERT_NOT_NOEXCEPT(H.resume());
|
||||
LIBCPP_ASSERT_NOT_NOEXCEPT(H());
|
||||
static_assert(has_resume<HType&>(), "");
|
||||
static_assert(has_resume<HType&&>(), "");
|
||||
static_assert(has_call_operator<HType&>(), "");
|
||||
static_assert(has_call_operator<HType&&>(), "");
|
||||
}
|
||||
{
|
||||
static_assert(!has_resume<HType const&>(), "");
|
||||
static_assert(!has_resume<HType const&&>(), "");
|
||||
static_assert(!has_call_operator<HType const&>(), "");
|
||||
static_assert(!has_call_operator<HType const&&>(), "");
|
||||
}
|
||||
}
|
||||
|
||||
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,72 @@
|
||||
// -*- 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 <cassert>
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
struct coro_t {
|
||||
struct promise_type {
|
||||
coro_t get_return_object() {
|
||||
coroutine_handle<promise_type>{};
|
||||
return {};
|
||||
}
|
||||
suspend_never initial_suspend() { return {}; }
|
||||
suspend_never final_suspend() { return {}; }
|
||||
void return_void(){}
|
||||
static void unhandled_exception() {}
|
||||
};
|
||||
};
|
||||
|
||||
struct B {
|
||||
~B() {}
|
||||
bool await_ready() { return true; }
|
||||
B await_resume() { return {}; }
|
||||
template <typename F> void await_suspend(F) {}
|
||||
};
|
||||
|
||||
|
||||
struct A {
|
||||
~A(){}
|
||||
bool await_ready() { return true; }
|
||||
int await_resume() { return 42; }
|
||||
template <typename F> void await_suspend(F) {}
|
||||
};
|
||||
|
||||
int last_value = -1;
|
||||
void set_value(int x) {
|
||||
last_value = x;
|
||||
}
|
||||
|
||||
coro_t f(int n) {
|
||||
if (n == 0) {
|
||||
set_value(0);
|
||||
co_return;
|
||||
}
|
||||
int val = co_await A{};
|
||||
set_value(42);
|
||||
}
|
||||
|
||||
coro_t g() { B val = co_await B{}; }
|
||||
|
||||
int main() {
|
||||
last_value = -1;
|
||||
f(0);
|
||||
assert(last_value == 0);
|
||||
f(1);
|
||||
assert(last_value == 42);
|
||||
}
|
@ -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
|
||||
|
||||
// FIXME: When run under UBSAN this test hits an assertion inside Clang
|
||||
// XFAIL: ubsan
|
||||
|
||||
// RUN: %build -fcoroutines-ts
|
||||
// RUN: %run
|
||||
|
||||
#include <experimental/coroutine>
|
||||
#include <cassert>
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
struct coro_t {
|
||||
struct promise_type {
|
||||
coro_t get_return_object() {
|
||||
return coroutine_handle<promise_type>::from_promise(*this);
|
||||
}
|
||||
suspend_never initial_suspend() { return {}; }
|
||||
suspend_never final_suspend() { return {}; }
|
||||
void return_void(){}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
coro_t(coroutine_handle<promise_type> hh) : h(hh) {}
|
||||
coroutine_handle<promise_type> h;
|
||||
};
|
||||
|
||||
struct NoSuspend {
|
||||
bool await_ready() { return false; }
|
||||
void await_resume() {}
|
||||
template <typename F> bool await_suspend(F) { return false; }
|
||||
};
|
||||
|
||||
struct DoSuspend {
|
||||
bool await_ready() { return false; }
|
||||
void await_resume() {}
|
||||
template <typename F> bool await_suspend(F) { return true; }
|
||||
};
|
||||
|
||||
bool f_started, f_resumed = false;
|
||||
coro_t f() {
|
||||
f_started = true;
|
||||
co_await DoSuspend{};
|
||||
f_resumed = true;
|
||||
}
|
||||
|
||||
bool g_started, g_resumed = false;
|
||||
coro_t g() {
|
||||
g_started = true;
|
||||
co_await NoSuspend{};
|
||||
g_resumed = true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
assert(!f_started && !f_resumed && !g_started && !g_resumed);
|
||||
auto fret = f();
|
||||
assert(f_started && !f_resumed);
|
||||
fret.h.destroy();
|
||||
assert(f_started && !f_resumed);
|
||||
g();
|
||||
assert(g_started && g_resumed);
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// -*- 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 <cassert>
|
||||
using namespace std::experimental;
|
||||
|
||||
struct error {};
|
||||
|
||||
template <typename T, typename Error = int>
|
||||
struct expected {
|
||||
|
||||
struct Data {
|
||||
T val;
|
||||
Error error;
|
||||
};
|
||||
Data data;
|
||||
|
||||
struct DataPtr {
|
||||
Data *p;
|
||||
~DataPtr() { delete p; }
|
||||
};
|
||||
|
||||
expected() {}
|
||||
expected(T val) : data{std::move(val),{}} {}
|
||||
expected(struct error, Error error) : data{{}, std::move(error)} {}
|
||||
expected(DataPtr & p) : data{std::move(p.p->val), std::move(p.p->error)} {}
|
||||
|
||||
struct promise_type {
|
||||
Data* data;
|
||||
DataPtr get_return_object() { data = new Data{}; return {data}; }
|
||||
suspend_never initial_suspend() { return {}; }
|
||||
suspend_never final_suspend() { return {}; }
|
||||
void return_value(T v) { data->val = std::move(v); data->error = {};}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
|
||||
bool await_ready() { return !data.error; }
|
||||
T await_resume() { return std::move(data.val); }
|
||||
void await_suspend(coroutine_handle<promise_type> h) {
|
||||
h.promise().data->error =std::move(data.error);
|
||||
h.destroy();
|
||||
}
|
||||
|
||||
T const& value() { return data.val; }
|
||||
Error const& error() { return data.error; }
|
||||
};
|
||||
|
||||
expected<int> g() { return {0}; }
|
||||
expected<int> h() { return {error{}, 42}; }
|
||||
|
||||
extern "C" void print(int);
|
||||
|
||||
bool f1_started, f1_resumed = false;
|
||||
expected<int> f1() {
|
||||
f1_started = true;
|
||||
(void)(co_await g());
|
||||
f1_resumed = true;
|
||||
co_return 100;
|
||||
}
|
||||
|
||||
bool f2_started, f2_resumed = false;
|
||||
expected<int> f2() {
|
||||
f2_started = true;
|
||||
(void)(co_await h());
|
||||
f2_resumed = true;
|
||||
co_return 200;
|
||||
}
|
||||
|
||||
int main() {
|
||||
auto c1 = f1();
|
||||
assert(f1_started && f1_resumed);
|
||||
assert(c1.value() == 100);
|
||||
assert(c1.error() == 0);
|
||||
|
||||
auto c2 = f2();
|
||||
assert(f2_started && !f2_resumed);
|
||||
assert(c2.value() == 0);
|
||||
assert(c2.error() == 42);
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
// -*- 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 <cassert>
|
||||
|
||||
#include "test_macros.h"
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
int alive = 0;
|
||||
int ctor_called = 0;
|
||||
int dtor_called = 0;
|
||||
void reset() {
|
||||
assert(alive == 0);
|
||||
alive = 0;
|
||||
ctor_called = 0;
|
||||
dtor_called = 0;
|
||||
}
|
||||
struct Noisy {
|
||||
Noisy() { ++alive; ++ctor_called; }
|
||||
~Noisy() { --alive; ++dtor_called; }
|
||||
#if TEST_STD_VER > 14
|
||||
Noisy(Noisy const&) = delete;
|
||||
#else
|
||||
// FIXME: This test depends on copy elision taking place in C++14
|
||||
// (pre-c++17 guaranteed copy elision)
|
||||
Noisy(Noisy const&);
|
||||
#endif
|
||||
};
|
||||
|
||||
struct Bug {
|
||||
bool await_ready() { return true; }
|
||||
void await_suspend(std::experimental::coroutine_handle<>) {}
|
||||
Noisy await_resume() { return {}; }
|
||||
};
|
||||
struct coro2 {
|
||||
struct promise_type {
|
||||
suspend_never initial_suspend() { return{}; }
|
||||
suspend_never final_suspend() { return{}; }
|
||||
coro2 get_return_object() { return{}; }
|
||||
void return_void() {}
|
||||
Bug yield_value(int) { return {}; }
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
};
|
||||
|
||||
// Checks that destructors are correctly invoked for the object returned by
|
||||
// coawait.
|
||||
coro2 a() {
|
||||
reset();
|
||||
{
|
||||
auto x = co_await Bug{};
|
||||
assert(alive == 1);
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 0);
|
||||
}
|
||||
assert(alive == 0);
|
||||
assert(dtor_called == 1);
|
||||
}
|
||||
|
||||
coro2 b() {
|
||||
reset();
|
||||
{
|
||||
co_await Bug{};
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 1);
|
||||
assert(alive == 0);
|
||||
}
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 1);
|
||||
assert(alive == 0);
|
||||
|
||||
}
|
||||
|
||||
coro2 c() {
|
||||
reset();
|
||||
{
|
||||
auto x = co_yield 42;
|
||||
assert(alive == 1);
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 0);
|
||||
}
|
||||
assert(alive == 0);
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 1);
|
||||
}
|
||||
|
||||
coro2 d() {
|
||||
reset();
|
||||
{
|
||||
co_yield 42;
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 1);
|
||||
assert(alive == 0);
|
||||
}
|
||||
assert(alive == 0);
|
||||
assert(ctor_called == 1);
|
||||
assert(dtor_called == 1);
|
||||
}
|
||||
|
||||
int main() {
|
||||
a();
|
||||
b();
|
||||
c();
|
||||
d();
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
// -*- 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
|
||||
|
||||
// FIXME: When run under UBSAN this test hits an assertion inside Clang
|
||||
// XFAIL: ubsan
|
||||
|
||||
// RUN: %build -fcoroutines-ts
|
||||
// RUN: %run
|
||||
|
||||
#include <experimental/coroutine>
|
||||
#include <vector>
|
||||
#include <cassert>
|
||||
|
||||
#include "coroutine_types.h"
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
struct minig {
|
||||
struct promise_type {
|
||||
int current_value;
|
||||
suspend_always yield_value(int value) {
|
||||
this->current_value = value;
|
||||
return {};
|
||||
}
|
||||
suspend_always initial_suspend() { return {}; }
|
||||
suspend_always final_suspend() { return {}; }
|
||||
minig get_return_object() { return minig{this}; };
|
||||
void return_void() {}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
|
||||
bool move_next() {
|
||||
p.resume();
|
||||
return !p.done();
|
||||
}
|
||||
int current_value() { return p.promise().current_value; }
|
||||
|
||||
minig(minig &&rhs) : p(rhs.p) { rhs.p = nullptr; }
|
||||
|
||||
~minig() {
|
||||
if (p)
|
||||
p.destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit minig(promise_type *p)
|
||||
: p(coroutine_handle<promise_type>::from_promise(*p)) {}
|
||||
|
||||
coroutine_handle<promise_type> p;
|
||||
};
|
||||
|
||||
|
||||
minig mini_count(int n) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
co_yield i;
|
||||
}
|
||||
}
|
||||
|
||||
generator<int> count(int n) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
co_yield i;
|
||||
}
|
||||
|
||||
generator<int> range(int from, int n) {
|
||||
for (int i = from; i < n; ++i)
|
||||
co_yield i;
|
||||
}
|
||||
|
||||
void test_count() {
|
||||
const std::vector<int> expect = {0, 1, 2, 3, 4};
|
||||
std::vector<int> got;
|
||||
for (auto x : count(5))
|
||||
got.push_back(x);
|
||||
assert(expect == got);
|
||||
}
|
||||
|
||||
void test_range() {
|
||||
int sum = 0;
|
||||
for (auto v: range(1, 20))
|
||||
sum += v;
|
||||
assert(sum == 190);
|
||||
}
|
||||
|
||||
void test_mini_generator() {
|
||||
int sum = 0;
|
||||
auto g = mini_count(5);
|
||||
while (g.move_next()) {
|
||||
sum += g.current_value();
|
||||
}
|
||||
assert(sum == 10);
|
||||
}
|
||||
|
||||
int main() {
|
||||
test_count();
|
||||
test_range();
|
||||
test_mini_generator();
|
||||
}
|
@ -0,0 +1,182 @@
|
||||
// -*- 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 <cassert>
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
bool cancel = false;
|
||||
|
||||
struct goroutine
|
||||
{
|
||||
static int const N = 10;
|
||||
static int count;
|
||||
static coroutine_handle<> stack[N];
|
||||
|
||||
static void schedule(coroutine_handle<>& rh)
|
||||
{
|
||||
assert(count < N);
|
||||
stack[count++] = rh;
|
||||
rh = nullptr;
|
||||
}
|
||||
|
||||
~goroutine() {}
|
||||
|
||||
static void go(goroutine) {}
|
||||
|
||||
static void run_one()
|
||||
{
|
||||
assert(count > 0);
|
||||
stack[--count]();
|
||||
}
|
||||
|
||||
struct promise_type
|
||||
{
|
||||
suspend_never initial_suspend() {
|
||||
return {};
|
||||
}
|
||||
suspend_never final_suspend() {
|
||||
return {};
|
||||
}
|
||||
void return_void() {}
|
||||
goroutine get_return_object() {
|
||||
return{};
|
||||
}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
};
|
||||
int goroutine::count;
|
||||
coroutine_handle<> goroutine::stack[N];
|
||||
|
||||
coroutine_handle<goroutine::promise_type> workaround;
|
||||
|
||||
class channel;
|
||||
|
||||
struct push_awaiter {
|
||||
channel* ch;
|
||||
bool await_ready() {return false; }
|
||||
void await_suspend(coroutine_handle<> rh);
|
||||
void await_resume() {}
|
||||
};
|
||||
|
||||
struct pull_awaiter {
|
||||
channel * ch;
|
||||
|
||||
bool await_ready();
|
||||
void await_suspend(coroutine_handle<> rh);
|
||||
int await_resume();
|
||||
};
|
||||
|
||||
class channel
|
||||
{
|
||||
using T = int;
|
||||
|
||||
friend struct push_awaiter;
|
||||
friend struct pull_awaiter;
|
||||
|
||||
T const* pvalue = nullptr;
|
||||
coroutine_handle<> reader = nullptr;
|
||||
coroutine_handle<> writer = nullptr;
|
||||
public:
|
||||
push_awaiter push(T const& value)
|
||||
{
|
||||
assert(pvalue == nullptr);
|
||||
assert(!writer);
|
||||
pvalue = &value;
|
||||
|
||||
return { this };
|
||||
}
|
||||
|
||||
pull_awaiter pull()
|
||||
{
|
||||
assert(!reader);
|
||||
|
||||
return { this };
|
||||
}
|
||||
|
||||
void sync_push(T const& value)
|
||||
{
|
||||
assert(!pvalue);
|
||||
pvalue = &value;
|
||||
assert(reader);
|
||||
reader();
|
||||
assert(!pvalue);
|
||||
reader = nullptr;
|
||||
}
|
||||
|
||||
auto sync_pull()
|
||||
{
|
||||
while (!pvalue) goroutine::run_one();
|
||||
auto result = *pvalue;
|
||||
pvalue = nullptr;
|
||||
if (writer)
|
||||
{
|
||||
auto wr = writer;
|
||||
writer = nullptr;
|
||||
wr();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
void push_awaiter::await_suspend(coroutine_handle<> rh)
|
||||
{
|
||||
ch->writer = rh;
|
||||
if (ch->reader) goroutine::schedule(ch->reader);
|
||||
}
|
||||
|
||||
|
||||
bool pull_awaiter::await_ready() {
|
||||
return !!ch->writer;
|
||||
}
|
||||
void pull_awaiter::await_suspend(coroutine_handle<> rh) {
|
||||
ch->reader = rh;
|
||||
}
|
||||
int pull_awaiter::await_resume() {
|
||||
auto result = *ch->pvalue;
|
||||
ch->pvalue = nullptr;
|
||||
if (ch->writer) {
|
||||
//goroutine::schedule(ch->writer);
|
||||
auto wr = ch->writer;
|
||||
ch->writer = nullptr;
|
||||
wr();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
goroutine pusher(channel& left, channel& right)
|
||||
{
|
||||
for (;;) {
|
||||
auto val = co_await left.pull();
|
||||
co_await right.push(val + 1);
|
||||
}
|
||||
}
|
||||
|
||||
const int N = 100; //100'000'000;
|
||||
const int repeat = 1;
|
||||
|
||||
channel* c = new channel[N + 1];
|
||||
|
||||
int main() {
|
||||
for (int i = 0; i < N; ++i)
|
||||
goroutine::go(pusher(c[i], c[i + 1]));
|
||||
|
||||
c[0].sync_push(0);
|
||||
int result = c[N].sync_pull();
|
||||
|
||||
assert(result == 100);
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
// -*- 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 <cassert>
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
// This file tests, multishot, movable std::function like thing using coroutine
|
||||
// for compile-time type erasure and unerasure.
|
||||
template <typename R> struct func {
|
||||
struct Input {R a, b;};
|
||||
|
||||
struct promise_type {
|
||||
Input* I;
|
||||
R result;
|
||||
func get_return_object() { return {this}; }
|
||||
suspend_always initial_suspend() { return {}; }
|
||||
suspend_never final_suspend() { return {}; }
|
||||
void return_void() {}
|
||||
template <typename F>
|
||||
suspend_always yield_value(F&& f) {
|
||||
result = f(I->a, I->b);
|
||||
return {};
|
||||
}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
|
||||
R operator()(Input I) {
|
||||
h.promise().I = &I;
|
||||
h.resume();
|
||||
R result = h.promise().result;
|
||||
return result;
|
||||
};
|
||||
|
||||
func() {}
|
||||
func(func &&rhs) : h(rhs.h) { rhs.h = nullptr; }
|
||||
func(func const &) = delete;
|
||||
|
||||
func &operator=(func &&rhs) {
|
||||
if (this != &rhs) {
|
||||
if (h)
|
||||
h.destroy();
|
||||
h = rhs.h;
|
||||
rhs.h = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename F> static func Create(F f) {
|
||||
for (;;) {
|
||||
co_yield f;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F> func(F f) : func(Create(f)) {}
|
||||
|
||||
~func() {
|
||||
if (h)
|
||||
h.destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
func(promise_type *promise)
|
||||
: h(coroutine_handle<promise_type>::from_promise(*promise)) {}
|
||||
coroutine_handle<promise_type> h;
|
||||
};
|
||||
|
||||
int Do(int acc, int n, func<int> f) {
|
||||
for (int i = 0; i < n; ++i)
|
||||
acc = f({acc, i});
|
||||
return acc;
|
||||
}
|
||||
|
||||
int main() {
|
||||
int result = Do(1, 10, [](int a, int b) {return a + b;});
|
||||
assert(result == 46);
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
// -*- 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 <vector>
|
||||
#include <cassert>
|
||||
|
||||
using namespace std::experimental;
|
||||
|
||||
// This file tests, one shot, movable std::function like thing using coroutine
|
||||
// for compile-time type erasure and unerasure.
|
||||
|
||||
template <typename R> struct func {
|
||||
struct promise_type {
|
||||
R result;
|
||||
func get_return_object() { return {this}; }
|
||||
suspend_always initial_suspend() { return {}; }
|
||||
suspend_always final_suspend() { return {}; }
|
||||
void return_value(R v) { result = v; }
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
|
||||
R operator()() {
|
||||
h.resume();
|
||||
R result = h.promise().result;
|
||||
h.destroy();
|
||||
h = nullptr;
|
||||
return result;
|
||||
};
|
||||
|
||||
func() {}
|
||||
func(func &&rhs) : h(rhs.h) { rhs.h = nullptr; }
|
||||
func(func const &) = delete;
|
||||
|
||||
func &operator=(func &&rhs) {
|
||||
if (this != &rhs) {
|
||||
if (h)
|
||||
h.destroy();
|
||||
h = rhs.h;
|
||||
rhs.h = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename F> static func Create(F f) { co_return f(); }
|
||||
|
||||
template <typename F> func(F f) : func(Create(f)) {}
|
||||
|
||||
~func() {
|
||||
if (h)
|
||||
h.destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
func(promise_type *promise)
|
||||
: h(coroutine_handle<promise_type>::from_promise(*promise)) {}
|
||||
coroutine_handle<promise_type> h;
|
||||
};
|
||||
|
||||
std::vector<int> yielded_values = {};
|
||||
int yield(int x) { yielded_values.push_back(x); return x + 1; }
|
||||
float fyield(int x) { yielded_values.push_back(x); return x + 2; }
|
||||
|
||||
void Do1(func<int> f) { yield(f()); }
|
||||
void Do2(func<double> f) { yield(f()); }
|
||||
|
||||
int main() {
|
||||
Do1([] { return yield(43); });
|
||||
assert((yielded_values == std::vector<int>{43, 44}));
|
||||
|
||||
yielded_values = {};
|
||||
Do2([] { return fyield(44); });
|
||||
assert((yielded_values == std::vector<int>{44, 46}));
|
||||
}
|
@ -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;
|
||||
|
||||
}
|
@ -24,6 +24,7 @@ test(S s, typename S::difference_type pos, S expected)
|
||||
typename S::const_iterator p = s.begin() + pos;
|
||||
typename S::iterator i = s.erase(p);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
assert(i - s.begin() == pos);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ test(S s, typename S::difference_type pos, typename S::difference_type n, S expe
|
||||
typename S::const_iterator last = s.cbegin() + pos + n;
|
||||
typename S::iterator i = s.erase(first, last);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
assert(i - s.begin() == pos);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ test(S s, S expected)
|
||||
{
|
||||
s.pop_back();
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ test(S s, typename S::size_type pos, typename S::size_type n, S expected)
|
||||
{
|
||||
s.erase(pos, n);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
@ -58,6 +59,7 @@ test(S s, typename S::size_type pos, S expected)
|
||||
{
|
||||
s.erase(pos);
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
}
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
@ -83,6 +85,7 @@ test(S s, S expected)
|
||||
{
|
||||
s.erase();
|
||||
LIBCPP_ASSERT(s.__invariants());
|
||||
assert(s[s.size()] == typename S::value_type());
|
||||
assert(s == expected);
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ void test_no_inner_alloc()
|
||||
using SA = std::scoped_allocator_adaptor<Alloc>;
|
||||
static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
|
||||
Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
|
||||
assert(ptr);
|
||||
Alloc CA(P);
|
||||
SA A(CA);
|
||||
A.construct(ptr);
|
||||
@ -61,6 +62,7 @@ void test_no_inner_alloc()
|
||||
using SA = std::scoped_allocator_adaptor<Alloc>;
|
||||
static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
|
||||
Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
|
||||
assert(ptr);
|
||||
Alloc CA(P);
|
||||
SA A(CA);
|
||||
A.construct(ptr);
|
||||
@ -77,7 +79,6 @@ void test_no_inner_alloc()
|
||||
|
||||
void test_with_inner_alloc()
|
||||
{
|
||||
using VoidAlloc1 = CountingAllocator<void, 1>;
|
||||
using VoidAlloc2 = CountingAllocator<void, 2>;
|
||||
|
||||
AllocController POuter;
|
||||
@ -93,6 +94,7 @@ void test_with_inner_alloc()
|
||||
static_assert(!std::uses_allocator<T, Outer>::value, "");
|
||||
static_assert(std::uses_allocator<T, Inner>::value, "");
|
||||
Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
|
||||
assert(ptr);
|
||||
Outer O(POuter);
|
||||
Inner I(PInner);
|
||||
SA A(O, I);
|
||||
@ -119,6 +121,7 @@ void test_with_inner_alloc()
|
||||
static_assert(!std::uses_allocator<T, Outer>::value, "");
|
||||
static_assert(std::uses_allocator<T, Inner>::value, "");
|
||||
Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
|
||||
assert(ptr);
|
||||
Outer O(POuter);
|
||||
Inner I(PInner);
|
||||
SA A(O, I);
|
||||
|
@ -45,6 +45,25 @@ struct Foo
|
||||
virtual ~Foo() = default;
|
||||
};
|
||||
|
||||
#ifdef _LIBCPP_VERSION
|
||||
struct Result {};
|
||||
static Result theFunction() { return Result(); }
|
||||
static int resultDeletorCount;
|
||||
static void resultDeletor(Result (*pf)()) {
|
||||
assert(pf == theFunction);
|
||||
++resultDeletorCount;
|
||||
}
|
||||
|
||||
void test_pointer_to_function() {
|
||||
{ // https://bugs.llvm.org/show_bug.cgi?id=27566
|
||||
std::shared_ptr<Result()> x(&theFunction, &resultDeletor);
|
||||
std::shared_ptr<Result()> y(theFunction, resultDeletor);
|
||||
}
|
||||
assert(resultDeletorCount == 2);
|
||||
}
|
||||
#else // _LIBCPP_VERSION
|
||||
void test_pointer_to_function() {}
|
||||
#endif // _LIBCPP_VERSION
|
||||
|
||||
int main()
|
||||
{
|
||||
@ -66,6 +85,8 @@ int main()
|
||||
assert(p2.get());
|
||||
}
|
||||
|
||||
test_pointer_to_function();
|
||||
|
||||
#if TEST_STD_VER >= 11
|
||||
nc = globalMemCounter.outstanding_new;
|
||||
{
|
||||
|
@ -32,6 +32,16 @@ void test(InitArgs&&... args)
|
||||
assert(*lhs == *rhs);
|
||||
}
|
||||
|
||||
template <class T, class ...InitArgs>
|
||||
constexpr bool constexpr_test(InitArgs&&... args)
|
||||
{
|
||||
static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement
|
||||
const optional<T> rhs(std::forward<InitArgs>(args)...);
|
||||
optional<T> lhs = rhs;
|
||||
return (lhs.has_value() == rhs.has_value()) &&
|
||||
(lhs.has_value() ? *lhs == *rhs : true);
|
||||
}
|
||||
|
||||
void test_throwing_ctor() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Z {
|
||||
@ -108,6 +118,9 @@ int main()
|
||||
{
|
||||
test<int>();
|
||||
test<int>(3);
|
||||
static_assert(constexpr_test<int>(), "" );
|
||||
static_assert(constexpr_test<int>(3), "" );
|
||||
|
||||
{
|
||||
const optional<const int> o(42);
|
||||
optional<const int> o2(o);
|
||||
|
@ -41,6 +41,17 @@ void test(InitArgs&&... args)
|
||||
assert(*lhs == *orig);
|
||||
}
|
||||
|
||||
template <class T, class ...InitArgs>
|
||||
constexpr bool constexpr_test(InitArgs&&... args)
|
||||
{
|
||||
static_assert( std::is_trivially_copy_constructible_v<T>, ""); // requirement
|
||||
const optional<T> orig(std::forward<InitArgs>(args)...);
|
||||
optional<T> rhs(orig);
|
||||
optional<T> lhs = std::move(rhs);
|
||||
return (lhs.has_value() == orig.has_value()) &&
|
||||
(lhs.has_value() ? *lhs == *orig : true);
|
||||
}
|
||||
|
||||
void test_throwing_ctor() {
|
||||
#ifndef TEST_HAS_NO_EXCEPTIONS
|
||||
struct Z {
|
||||
@ -144,6 +155,9 @@ int main()
|
||||
{
|
||||
test<int>();
|
||||
test<int>(3);
|
||||
static_assert(constexpr_test<int>(), "" );
|
||||
static_assert(constexpr_test<int>(3), "" );
|
||||
|
||||
{
|
||||
optional<const int> o(42);
|
||||
optional<const int> o2(std::move(o));
|
||||
|
@ -149,7 +149,7 @@ constexpr bool test_constexpr_copy_ctor_extension_imp(
|
||||
}
|
||||
|
||||
void test_constexpr_copy_ctor_extension() {
|
||||
#if defined(_LIBCPP_VER) || defined(_MSVC_STL_VER)
|
||||
// NOTE: This test is for not yet standardized behavior.
|
||||
using V = std::variant<long, void*, const int>;
|
||||
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||
static_assert(std::is_trivially_destructible<V>::value, "");
|
||||
@ -163,7 +163,6 @@ void test_constexpr_copy_ctor_extension() {
|
||||
static_assert(test_constexpr_copy_ctor_extension_imp<0>(V(42l)), "");
|
||||
static_assert(test_constexpr_copy_ctor_extension_imp<1>(V(nullptr)), "");
|
||||
static_assert(test_constexpr_copy_ctor_extension_imp<2>(V(101)), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
@ -186,7 +186,7 @@ constexpr bool test_constexpr_ctor_extension_imp(
|
||||
}
|
||||
|
||||
void test_constexpr_move_ctor_extension() {
|
||||
#if defined(_LIBCPP_VER) || defined(_MSVC_STL_VER)
|
||||
// NOTE: This test is for not yet standardized behavior.
|
||||
using V = std::variant<long, void*, const int>;
|
||||
#ifdef TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||
static_assert(std::is_trivially_destructible<V>::value, "");
|
||||
@ -201,7 +201,6 @@ void test_constexpr_move_ctor_extension() {
|
||||
static_assert(test_constexpr_ctor_extension_imp<0>(V(42l)), "");
|
||||
static_assert(test_constexpr_ctor_extension_imp<1>(V(nullptr)), "");
|
||||
static_assert(test_constexpr_ctor_extension_imp<2>(V(101)), "");
|
||||
#endif
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
75
test/support/coroutine_types.h
Normal file
75
test/support/coroutine_types.h
Normal file
@ -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.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef SUPPORT_COROUTINE_TYPES_H
|
||||
#define SUPPORT_COROUTINE_TYPES_H
|
||||
|
||||
#include <experimental/coroutine>
|
||||
|
||||
template <typename Ty> struct generator {
|
||||
struct promise_type {
|
||||
Ty current_value;
|
||||
std::experimental::suspend_always yield_value(Ty value) {
|
||||
this->current_value = value;
|
||||
return {};
|
||||
}
|
||||
std::experimental::suspend_always initial_suspend() { return {}; }
|
||||
std::experimental::suspend_always final_suspend() { return {}; }
|
||||
generator get_return_object() { return generator{this}; };
|
||||
void return_void() {}
|
||||
void unhandled_exception() {}
|
||||
};
|
||||
|
||||
struct iterator {
|
||||
std::experimental::coroutine_handle<promise_type> _Coro;
|
||||
bool _Done;
|
||||
|
||||
iterator(std::experimental::coroutine_handle<promise_type> Coro, bool Done)
|
||||
: _Coro(Coro), _Done(Done) {}
|
||||
|
||||
iterator &operator++() {
|
||||
_Coro.resume();
|
||||
_Done = _Coro.done();
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(iterator const &_Right) const {
|
||||
return _Done == _Right._Done;
|
||||
}
|
||||
|
||||
bool operator!=(iterator const &_Right) const { return !(*this == _Right); }
|
||||
|
||||
Ty const &operator*() const { return _Coro.promise().current_value; }
|
||||
|
||||
Ty const *operator->() const { return &(operator*()); }
|
||||
};
|
||||
|
||||
iterator begin() {
|
||||
p.resume();
|
||||
return {p, p.done()};
|
||||
}
|
||||
|
||||
iterator end() { return {p, true}; }
|
||||
|
||||
generator(generator &&rhs) : p(rhs.p) { rhs.p = nullptr; }
|
||||
|
||||
~generator() {
|
||||
if (p)
|
||||
p.destroy();
|
||||
}
|
||||
|
||||
private:
|
||||
explicit generator(promise_type *p)
|
||||
: p(std::experimental::coroutine_handle<promise_type>::from_promise(*p)) {}
|
||||
|
||||
std::experimental::coroutine_handle<promise_type> p;
|
||||
};
|
||||
|
||||
#endif // SUPPORT_COROUTINE_TYPES_H
|
@ -50,10 +50,8 @@ namespace PoisonedHashDetail {
|
||||
// specializations of hash for nullptr t and all cv-unqualified
|
||||
// arithmetic, enumeration, and pointer types.
|
||||
using LibraryHashTypes = TypeList<
|
||||
#if !defined(TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR)
|
||||
#if TEST_STD_VER > 14
|
||||
decltype(nullptr),
|
||||
#endif
|
||||
#endif
|
||||
bool,
|
||||
char,
|
||||
|
@ -1,29 +0,0 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// Verify TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_workarounds.h"
|
||||
|
||||
struct ConvertsToNullptr {
|
||||
using DestType = decltype(nullptr);
|
||||
operator DestType() const { return nullptr; }
|
||||
};
|
||||
|
||||
int main() {
|
||||
#if defined(TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR)
|
||||
static_assert(!std::is_convertible<ConvertsToNullptr, decltype(nullptr)>::value, "");
|
||||
#else
|
||||
static_assert(std::is_convertible<ConvertsToNullptr, decltype(nullptr)>::value, "");
|
||||
#endif
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// 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
|
||||
|
||||
// Verify TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION.
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_workarounds.h"
|
||||
|
||||
template<class T>
|
||||
struct identity {
|
||||
using type = T;
|
||||
};
|
||||
|
||||
template<class...> struct list {};
|
||||
|
||||
// C1XX believes this function template is not viable when LArgs is an empty
|
||||
// parameter pack.
|
||||
template <class ...LArgs>
|
||||
int f2(typename identity<LArgs>::type..., int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
#ifdef TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION
|
||||
// C1XX believes this function template *is* viable when LArgs is an empty
|
||||
// parameter pack. Conforming compilers believe the two overloads are
|
||||
// ambiguous when LArgs is an empty pack.
|
||||
template <class ...LArgs>
|
||||
int f2(int i) {
|
||||
return i;
|
||||
}
|
||||
#endif
|
||||
|
||||
template <class ...LArgs, class ...Args>
|
||||
int f1(list<LArgs...>, Args&&... args) {
|
||||
return f2<LArgs const&...>(args...);
|
||||
}
|
||||
|
||||
int main() {
|
||||
f1(list<>{}, 42);
|
||||
}
|
@ -154,6 +154,12 @@
|
||||
#define TEST_NORETURN [[noreturn]]
|
||||
#endif
|
||||
|
||||
#if defined(_LIBCPP_SAFE_STATIC)
|
||||
#define TEST_SAFE_STATIC _LIBCPP_SAFE_STATIC
|
||||
#else
|
||||
#define TEST_SAFE_STATIC
|
||||
#endif
|
||||
|
||||
#if TEST_STD_VER < 11
|
||||
#define ASSERT_NOEXCEPT(...)
|
||||
#define ASSERT_NOT_NOEXCEPT(...)
|
||||
|
@ -14,14 +14,14 @@
|
||||
#include "test_macros.h"
|
||||
|
||||
#if defined(TEST_COMPILER_EDG)
|
||||
# define TEST_WORKAROUND_EDG_EXPLICIT_CONSTEXPR
|
||||
# define TEST_WORKAROUND_EDG_EXPLICIT_CONSTEXPR // VSO#424280
|
||||
#endif
|
||||
|
||||
#if defined(TEST_COMPILER_C1XX)
|
||||
# define TEST_WORKAROUND_C1XX_BROKEN_NULLPTR_CONVERSION_OPERATOR
|
||||
# define TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE
|
||||
# define TEST_WORKAROUND_C1XX_BROKEN_IS_TRIVIALLY_COPYABLE // VSO#117743
|
||||
# define TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION // VSO#109062
|
||||
# ifndef _MSC_EXTENSIONS
|
||||
# define TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK
|
||||
# define TEST_WORKAROUND_C1XX_BROKEN_ZA_CTOR_CHECK // VSO#119998
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include <cstdlib>
|
||||
|
||||
#include "test_macros.h"
|
||||
#include "test_workarounds.h"
|
||||
#include "type_id.h"
|
||||
|
||||
// There are two forms of uses-allocator construction:
|
||||
@ -256,6 +257,13 @@ struct UsesAllocatorTestBase {
|
||||
return alloc;
|
||||
}
|
||||
|
||||
#ifdef TEST_WORKAROUND_C1XX_EMPTY_PARAMETER_PACK_EXPANSION
|
||||
template <class ...LArgs>
|
||||
static CtorAlloc getAllocatorFromPackImp(CtorAlloc const& alloc) {
|
||||
return alloc;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool has_alloc() const { return alloc_store.get_allocator() != nullptr; }
|
||||
const CtorAlloc *get_alloc() const { return alloc_store.get_allocator(); }
|
||||
public:
|
||||
|
@ -142,6 +142,7 @@ def configure(self):
|
||||
self.configure_sanitizer()
|
||||
self.configure_coverage()
|
||||
self.configure_modules()
|
||||
self.configure_coroutines()
|
||||
self.configure_substitutions()
|
||||
self.configure_features()
|
||||
|
||||
@ -954,6 +955,18 @@ def configure_coverage(self):
|
||||
self.cxx.flags += ['-g', '--coverage']
|
||||
self.cxx.compile_flags += ['-O0']
|
||||
|
||||
def configure_coroutines(self):
|
||||
if self.cxx.hasCompileFlag('-fcoroutines-ts'):
|
||||
macros = self.cxx.dumpMacros(flags=['-fcoroutines-ts'])
|
||||
if '__cpp_coroutines' not in macros:
|
||||
self.lit_config.warning('-fcoroutines-ts is supported but '
|
||||
'__cpp_coroutines is not defined')
|
||||
# Consider coroutines supported only when the feature test macro
|
||||
# reflects a recent value.
|
||||
val = macros['__cpp_coroutines'].replace('L', '')
|
||||
if int(val) >= 201703:
|
||||
self.config.available_features.add('fcoroutines-ts')
|
||||
|
||||
def configure_modules(self):
|
||||
modules_flags = ['-fmodules']
|
||||
if platform.system() != 'Darwin':
|
||||
|
@ -71,13 +71,13 @@
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4366">N4366</a></td><td>LWG</td></td><td>LWG 2228 missing SFINAE rule</td><td>Lenexa</td><td>Complete</td><td>3.1</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4510">N4510</a></td><td>LWG</td></td><td>Minimal incomplete type support for standard containers, revision 4</td><td>Lenexa</td><td>Complete</td><td>3.6</td></tr>
|
||||
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0004R1.html">P0004R1</a></td><td>LWG</td><td>Remove Deprecated iostreams aliases.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0004r1.html">P0004R1</a></td><td>LWG</td><td>Remove Deprecated iostreams aliases.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0006r0.html">P0006R0</a></td><td>LWG</td><td>Adopt Type Traits Variable Templates for C++17.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0092R1.html">P0092R1</a></td><td>LWG</td><td>Polishing <chrono></td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0007R1.html">P0007R1</a></td><td>LWG</td><td>Constant View: A proposal for a <tt>std::as_const</tt> helper function template.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0092r1.html">P0092R1</a></td><td>LWG</td><td>Polishing <chrono></td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0007r1.html">P0007R1</a></td><td>LWG</td><td>Constant View: A proposal for a <tt>std::as_const</tt> helper function template.</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0156r0.html" >P0156R0</a></td><td>LWG</td><td>Variadic lock_guard(rev 3).</td><td>Kona</td><td><I>Reverted in Kona</I></td><td>3.9</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0074R0.html">P0074R0</a></td><td>LWG</td><td>Making <tt>std::owner_less</tt> more flexible</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/P0013R1.html">P0013R1</a></td><td>LWG</td><td>Logical type traits rev 2</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0074r0.html">P0074R0</a></td><td>LWG</td><td>Making <tt>std::owner_less</tt> more flexible</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0013r1.html">P0013R1</a></td><td>LWG</td><td>Logical type traits rev 2</td><td>Kona</td><td>Complete</td><td>3.8</td></tr>
|
||||
<tr><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/P0024R2">P0024R2</a></td><td>LWG</td><td>The Parallelism TS Should be Standardized</td><td>Jacksonville</td><td></td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/P0226R1">P0226R1</a></td><td>LWG</td><td>Mathematical Special Functions for C++17</td><td>Jacksonville</td><td></td><td></td></tr>
|
||||
@ -444,7 +444,7 @@
|
||||
<tr><td><a href="http://wg21.link/LWG2787">2787</a></td><td>§[file_status.cons] doesn't match class definition</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2788">2788</a></td><td>basic_string range mutators unintentionally require a default constructible allocator</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2789">2789</a></td><td>Equivalence of contained objects</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2790">2790</a></td><td>Missing specification of istreambuf_iterator::operator-></td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2790">2790</a></td><td>Missing specification of istreambuf_iterator::operator-></td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2794">2794</a></td><td>Missing requirements for allocator pointers</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2795">2795</a></td><td>§[global.functions] provides incorrect example of ADL use</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2796">2796</a></td><td>tuple should be a literal type</td><td>Kona</td><td>Complete</td></tr>
|
||||
@ -475,7 +475,7 @@
|
||||
<tr><td><a href="http://wg21.link/LWG2876">2876</a></td><td>shared_ptr::shared_ptr(const weak_ptr<Y>&) constructor should be constrained</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2878">2878</a></td><td>Missing DefaultConstructible requirement for istream_iterator default constructor</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2890">2890</a></td><td>The definition of 'object state' applies only to class types</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2900">2900</a></td><td>The copy and move constructors of optional are not constexpr</td><td>Kona</td><td>Complete</td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2903">2903</a></td><td>The form of initialization for the emplace-constructors is not specified</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2904">2904</a></td><td>Make variant move-assignment more exception safe</td><td>Kona</td><td></td></tr>
|
||||
<tr><td><a href="http://wg21.link/LWG2905">2905</a></td><td>is_constructible_v<unique_ptr<P, D>, P, D const &> should be false when D is not copy constructible</td><td>Kona</td><td>Complete</td></tr>
|
||||
@ -489,7 +489,7 @@
|
||||
<!-- <tr><td></td><td></td><td></td><td></td></tr> -->
|
||||
</table>
|
||||
|
||||
<p>Last Updated: 11-May-2017</p>
|
||||
<p>Last Updated: 25-May-2017</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user