aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2017-05-29 16:26:10 +0000
committerDimitry Andric <dim@FreeBSD.org>2017-05-29 16:26:10 +0000
commitb276b1db48faa7328575ab722fe3bc340623f025 (patch)
tree9e4ba424f754c3f05e409ae647fa358031d97617
parentd1bd27794dfbc317e27d1ec63b338115cbf194ba (diff)
downloadsrc-b276b1db48faa7328575ab722fe3bc340623f025.tar.gz
src-b276b1db48faa7328575ab722fe3bc340623f025.zip
Vendor import of libc++ trunk r304149:vendor/libc++/libc++-trunk-r304149
Notes
Notes: svn path=/vendor/libc++/dist/; revision=319146 svn path=/vendor/libc++/libc++-trunk-r304149/; revision=319147; tag=vendor/libc++/libc++-trunk-r304149
-rw-r--r--CMakeLists.txt5
-rw-r--r--cmake/config-ix.cmake10
-rw-r--r--include/__config4
-rw-r--r--include/__threading_support2
-rw-r--r--include/algorithm23
-rw-r--r--include/experimental/__config7
-rw-r--r--include/experimental/coroutine270
-rw-r--r--include/iterator1
-rw-r--r--include/memory53
-rw-r--r--include/module.modulemap4
-rw-r--r--lib/CMakeLists.txt7
-rw-r--r--test/libcxx/double_include.sh.cpp3
-rw-r--r--test/libcxx/experimental/language.support/support.coroutines/dialect_support.sh.cpp59
-rw-r--r--test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp (renamed from test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op_astrk/arrow.pass.cpp)23
-rw-r--r--test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/function_type_default_deleter.fail.cpp44
-rw-r--r--test/std/algorithms/alg.nonmodifying/alg.foreach/for_each_n.pass.cpp61
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp62
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp64
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp73
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp48
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp58
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp57
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp55
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp50
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp67
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp53
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp65
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp84
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp55
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp81
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp73
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp75
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/await_result.sh.cpp72
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/bool_await_suspend.sh.cpp73
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/expected.sh.cpp93
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/fullexpr-dtor.sh.cpp120
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/generator.sh.cpp107
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/go.sh.cpp182
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/multishot_func.sh.cpp91
-rw-r--r--test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.sh.cpp87
-rw-r--r--test/std/experimental/language.support/support.coroutines/includes.sh.cpp31
-rw-r--r--test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp1
-rw-r--r--test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp1
-rw-r--r--test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp1
-rw-r--r--test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp3
-rw-r--r--test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp5
-rw-r--r--test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp21
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp13
-rw-r--r--test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp14
-rw-r--r--test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp3
-rw-r--r--test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp3
-rw-r--r--test/support/coroutine_types.h75
-rw-r--r--test/support/poisoned_hash_helper.hpp2
-rw-r--r--test/support/test.workarounds/c1xx_broken_nullptr_conversion_operator.pass.cpp29
-rw-r--r--test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp49
-rw-r--r--test/support/test_macros.h6
-rw-r--r--test/support/test_workarounds.h8
-rw-r--r--test/support/uses_alloc_types.hpp8
-rw-r--r--utils/libcxx/test/config.py13
-rw-r--r--www/cxx1z_status.html16
60 files changed, 2642 insertions, 81 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c25a0a0e40a..33d888b807da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake
index c425c31ea095..730ee7e164a6 100644
--- a/cmake/config-ix.cmake
+++ b/cmake/config-ix.cmake
@@ -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")
diff --git a/include/__config b/include/__config
index 4ad700e234c2..32e542bd1fd7 100644
--- a/include/__config
+++ b/include/__config
@@ -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.
diff --git a/include/__threading_support b/include/__threading_support
index 385fff32b350..afd7cb506492 100644
--- a/include/__threading_support
+++ b/include/__threading_support
@@ -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>
diff --git a/include/algorithm b/include/algorithm
index 08ca23ff6168..7ea4474a1bb4 100644
--- a/include/algorithm
+++ b/include/algorithm
@@ -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>
diff --git a/include/experimental/__config b/include/experimental/__config
index 9a7bbe85d8d3..37f88c166dd2 100644
--- a/include/experimental/__config
+++ b/include/experimental/__config
@@ -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
diff --git a/include/experimental/coroutine b/include/experimental/coroutine
new file mode 100644
index 000000000000..d2a03ae8a8c8
--- /dev/null
+++ b/include/experimental/coroutine
@@ -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 */
diff --git a/include/iterator b/include/iterator
index 4aa44746dc96..d163ab1b0910 100644
--- a/include/iterator
+++ b/include/iterator
@@ -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();
diff --git a/include/memory b/include/memory
index 4201c92dd723..31dc73d8b142 100644
--- a/include/memory
+++ b/include/memory
@@ -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();
diff --git a/include/module.modulemap b/include/module.modulemap
index c354cae1e5f1..462d4234ae6c 100644
--- a/include/module.modulemap
+++ b/include/module.modulemap
@@ -501,6 +501,10 @@ module std [system] {
header "experimental/chrono"
export *
}
+ module coroutine {
+ header "experimental/coroutine"
+ export *
+ }
module deque {
header "experimental/deque"
export *
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 6161838d0dfd..fe45f5ac0fe5 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -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")
diff --git a/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp
index 46dfc999be8b..0a9e9fcfaea8 100644
--- a/test/libcxx/double_include.sh.cpp
+++ b/test/libcxx/double_include.sh.cpp
@@ -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>
diff --git a/test/libcxx/experimental/language.support/support.coroutines/dialect_support.sh.cpp b/test/libcxx/experimental/language.support/support.coroutines/dialect_support.sh.cpp
new file mode 100644
index 000000000000..56f47c8faf42
--- /dev/null
+++ b/test/libcxx/experimental/language.support/support.coroutines/dialect_support.sh.cpp
@@ -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();
+}
diff --git a/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op_astrk/arrow.pass.cpp b/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp
index e3bf5e2bd84f..229ce10dd044 100644
--- a/test/std/iterators/stream.iterators/istreambuf.iterator/istreambuf.iterator_op_astrk/arrow.pass.cpp
+++ b/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp
@@ -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!
}
diff --git a/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/function_type_default_deleter.fail.cpp b/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/function_type_default_deleter.fail.cpp
new file mode 100644
index 000000000000..87cd29264b4e
--- /dev/null
+++ b/test/libcxx/utilities/memory/util.smartptr/util.smartptr.shared/function_type_default_deleter.fail.cpp
@@ -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}}
+ }
+}
diff --git a/test/std/algorithms/alg.nonmodifying/alg.foreach/for_each_n.pass.cpp b/test/std/algorithms/alg.nonmodifying/alg.foreach/for_each_n.pass.cpp
new file mode 100644
index 000000000000..fd24edb43060
--- /dev/null
+++ b/test/std/algorithms/alg.nonmodifying/alg.foreach/for_each_n.pass.cpp
@@ -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));
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp
new file mode 100644
index 000000000000..a744f56eb811
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp
@@ -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>>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp
new file mode 100644
index 000000000000..05c3f230e5ca
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp
@@ -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);
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp
new file mode 100644
index 000000000000..7b3bcc394c8c
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp
@@ -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);
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp
new file mode 100644
index 000000000000..48c3ca50cbf1
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp
@@ -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>{});
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp
new file mode 100644
index 000000000000..9e7fb5b2f687
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp
@@ -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>>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp
new file mode 100644
index 000000000000..961253fb7ca5
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp
@@ -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>>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp
new file mode 100644
index 000000000000..7258f93905f3
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp
@@ -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>>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp
new file mode 100644
index 000000000000..26a45b033ff5
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp
@@ -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>>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp
new file mode 100644
index 000000000000..5f66b3e11314
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp
@@ -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);
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp
new file mode 100644
index 000000000000..b38d7871be4b
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp
@@ -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>{});
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp
new file mode 100644
index 000000000000..9cc0d1d72bf7
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp
@@ -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>{});
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp
new file mode 100644
index 000000000000..b5ff187a49ce
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp
@@ -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>{});
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp
new file mode 100644
index 000000000000..945304a4673d
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp
@@ -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>();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp
new file mode 100644
index 000000000000..c1d3b818d403
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp
@@ -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>();
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp
new file mode 100644
index 000000000000..1987f68e70ab
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp
@@ -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(), "");
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp b/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp
new file mode 100644
index 000000000000..72e0ac024558
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp
@@ -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(), "");
+ }
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/await_result.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/await_result.sh.cpp
new file mode 100644
index 000000000000..cca875d1a6ba
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/await_result.sh.cpp
@@ -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);
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/bool_await_suspend.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/bool_await_suspend.sh.cpp
new file mode 100644
index 000000000000..e51ac67f0fef
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/bool_await_suspend.sh.cpp
@@ -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);
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/expected.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/expected.sh.cpp
new file mode 100644
index 000000000000..b6832b0c1886
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/expected.sh.cpp
@@ -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);
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/fullexpr-dtor.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/fullexpr-dtor.sh.cpp
new file mode 100644
index 000000000000..c7e34fe919e1
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/fullexpr-dtor.sh.cpp
@@ -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();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/generator.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/generator.sh.cpp
new file mode 100644
index 000000000000..4681793ed814
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/generator.sh.cpp
@@ -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();
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/go.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/go.sh.cpp
new file mode 100644
index 000000000000..e0d69104fdaf
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/go.sh.cpp
@@ -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);
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/multishot_func.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/multishot_func.sh.cpp
new file mode 100644
index 000000000000..e13196c253ea
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/multishot_func.sh.cpp
@@ -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);
+}
diff --git a/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.sh.cpp b/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.sh.cpp
new file mode 100644
index 000000000000..9c94f73b2a70
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/end.to.end/oneshot_func.sh.cpp
@@ -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}));
+}
diff --git a/test/std/experimental/language.support/support.coroutines/includes.sh.cpp b/test/std/experimental/language.support/support.coroutines/includes.sh.cpp
new file mode 100644
index 000000000000..f9d8a572256c
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/includes.sh.cpp
@@ -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;
+
+}
diff --git a/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
index 8de5fc7bab85..31add9df27a4 100644
--- a/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
+++ b/test/std/strings/basic.string/string.modifiers/string_erase/iter.pass.cpp
@@ -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);
}
diff --git a/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
index e4fe2cdfd022..858d3754e9da 100644
--- a/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
+++ b/test/std/strings/basic.string/string.modifiers/string_erase/iter_iter.pass.cpp
@@ -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);
}
diff --git a/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
index 64f8e506b13e..8424b5429cea 100644
--- a/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
+++ b/test/std/strings/basic.string/string.modifiers/string_erase/pop_back.pass.cpp
@@ -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);
}
diff --git a/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp b/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
index eb6be202a350..2c900bb315bc 100644
--- a/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
+++ b/test/std/strings/basic.string/string.modifiers/string_erase/size_size.pass.cpp
@@ -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);
}
diff --git a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp
index 4e73d8064317..82d63ecada48 100644
--- a/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp
+++ b/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp
@@ -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);
diff --git a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
index 2a7ac9979d02..f8f73f771356 100644
--- a/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
+++ b/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/make_shared.pass.cpp
@@ -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;
{
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
index 76c1fb82b866..6b4283a2854b 100644
--- a/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/copy.pass.cpp
@@ -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);
diff --git a/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
index 09aaa0561b51..82acdd9d7758 100644
--- a/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
+++ b/test/std/utilities/optional/optional.object/optional.object.ctor/move.pass.cpp
@@ -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));
diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
index a695df14ef62..3b20c369c638 100644
--- a/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
+++ b/test/std/utilities/variant/variant.variant/variant.ctor/copy.pass.cpp
@@ -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() {
diff --git a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp
index b8ca6f9ef27a..a5de1f77334e 100644
--- a/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp
+++ b/test/std/utilities/variant/variant.variant/variant.ctor/move.pass.cpp
@@ -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() {
diff --git a/test/support/coroutine_types.h b/test/support/coroutine_types.h
new file mode 100644
index 000000000000..f592bedca7f2
--- /dev/null
+++ b/test/support/coroutine_types.h
@@ -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
diff --git a/test/support/poisoned_hash_helper.hpp b/test/support/poisoned_hash_helper.hpp
index 824c35837b2b..6f42ebf8b480 100644
--- a/test/support/poisoned_hash_helper.hpp
+++ b/test/support/poisoned_hash_helper.hpp
@@ -50,11 +50,9 @@ 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,
signed char,
diff --git a/test/support/test.workarounds/c1xx_broken_nullptr_conversion_operator.pass.cpp b/test/support/test.workarounds/c1xx_broken_nullptr_conversion_operator.pass.cpp
deleted file mode 100644
index 250d06d2b902..000000000000
--- a/test/support/test.workarounds/c1xx_broken_nullptr_conversion_operator.pass.cpp
+++ /dev/null
@@ -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
-}
diff --git a/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp b/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp
new file mode 100644
index 000000000000..f25a9c9984cc
--- /dev/null
+++ b/test/support/test.workarounds/c1xx_empty_parameter_pack_expansion.pass.cpp
@@ -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);
+}
diff --git a/test/support/test_macros.h b/test/support/test_macros.h
index 6b573d40fe68..637686284ed2 100644
--- a/test/support/test_macros.h
+++ b/test/support/test_macros.h
@@ -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(...)
diff --git a/test/support/test_workarounds.h b/test/support/test_workarounds.h
index 614cec7aab86..ae123d7e41d0 100644
--- a/test/support/test_workarounds.h
+++ b/test/support/test_workarounds.h
@@ -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
diff --git a/test/support/uses_alloc_types.hpp b/test/support/uses_alloc_types.hpp
index 8422f809ba76..7f92f0fd19c7 100644
--- a/test/support/uses_alloc_types.hpp
+++ b/test/support/uses_alloc_types.hpp
@@ -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 @@ private:
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:
diff --git a/utils/libcxx/test/config.py b/utils/libcxx/test/config.py
index 2118f9c7eb90..1bf2677a8509 100644
--- a/utils/libcxx/test/config.py
+++ b/utils/libcxx/test/config.py
@@ -142,6 +142,7 @@ class Configuration(object):
self.configure_sanitizer()
self.configure_coverage()
self.configure_modules()
+ self.configure_coroutines()
self.configure_substitutions()
self.configure_features()
@@ -954,6 +955,18 @@ class Configuration(object):
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':
diff --git a/www/cxx1z_status.html b/www/cxx1z_status.html
index 101ad43212e5..80b53021c1f0 100644
--- a/www/cxx1z_status.html
+++ b/www/cxx1z_status.html
@@ -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>