Vendor import of libc++ trunk r304149:

https://llvm.org/svn/llvm-project/libcxx/trunk@304149
This commit is contained in:
Dimitry Andric 2017-05-29 16:26:10 +00:00
parent d1bd27794d
commit b276b1db48
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/vendor/libc++/dist/; revision=319146
svn path=/vendor/libc++/libc++-trunk-r304149/; revision=319147; tag=vendor/libc++/libc++-trunk-r304149
60 changed files with 2642 additions and 81 deletions

View File

@ -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)

View File

@ -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")

View File

@ -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.

View File

@ -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>

View File

@ -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>

View File

@ -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

View 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 */

View File

@ -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();

View File

@ -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();

View File

@ -500,6 +500,10 @@ module std [system] {
module chrono {
header "experimental/chrono"
export *
}
module coroutine {
header "experimental/coroutine"
export *
}
module deque {
header "experimental/deque"

View File

@ -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")

View File

@ -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>

View File

@ -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();
}

View File

@ -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!
}

View File

@ -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}}
}
}

View File

@ -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));
}
}

View File

@ -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>>();
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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>{});
}

View File

@ -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>>();
}

View File

@ -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>>();
}

View File

@ -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>>();
}

View File

@ -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>>();
}

View File

@ -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);
}
}

View File

@ -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>{});
}

View File

@ -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>{});
}

View File

@ -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>{});
}

View File

@ -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>();
}

View File

@ -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>();
}
}

View File

@ -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(), "");
}
}

View 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.
//
//===----------------------------------------------------------------------===//
// 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(), "");
}
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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}));
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
{

View File

@ -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);

View File

@ -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));

View File

@ -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() {

View File

@ -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() {

View 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

View File

@ -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,

View File

@ -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
}

View File

@ -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);
}

View File

@ -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(...)

View File

@ -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

View File

@ -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:

View File

@ -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':

View File

@ -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 &lt;chrono&gt;</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 &lt;chrono&gt;</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>&sect;[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-&gt;</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-&gt;</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>&sect;[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&lt;Y&gt;&amp;) 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&lt;unique_ptr&lt;P, D&gt;, P, D const &amp;&gt; 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>