summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt5
-rw-r--r--include/experimental/__config7
-rw-r--r--include/experimental/coroutine260
-rw-r--r--include/module.modulemap4
-rw-r--r--test/libcxx/double_include.sh.cpp3
-rw-r--r--test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp25
-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.cpp54
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp48
-rw-r--r--test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp51
-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/includes.sh.cpp31
-rw-r--r--test/support/test_macros.h6
-rw-r--r--utils/libcxx/test/config.py5
25 files changed, 1317 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8c25a0a0e..33d888b80 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/include/experimental/__config b/include/experimental/__config
index 9a7bbe85d..37f88c166 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 000000000..208a4d217
--- /dev/null
+++ b/include/experimental/coroutine
@@ -0,0 +1,260 @@
+// -*- C++ -*-
+//===----------------------------- coroutine -----------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP_EXPERIMENTAL_COROUTINE
+#define _LIBCPP_EXPERIMENTAL_COROUTINE
+
+/**
+ experimental/coroutine synopsis
+
+// C++next
+
+namespace std {
+namespace experimental {
+inline namespace coroutines_v1 {
+
+ // 18.11.1 coroutine traits
+template <typename R, typename... ArgTypes>
+class coroutine_traits;
+// 18.11.2 coroutine handle
+template <typename Promise = void>
+class coroutine_handle;
+// 18.11.2.7 comparison operators:
+bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+bool operator!=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+bool operator<=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+bool operator>=(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+bool operator>(coroutine_handle<> x, coroutine_handle<> y) noexcept;
+// 18.11.3 trivial awaitables
+struct suspend_never;
+struct suspend_always;
+// 18.11.2.8 hash support:
+template <class T> struct hash;
+template <class P> struct hash<coroutine_handle<P>>;
+
+} // namespace coroutines_v1
+} // namespace experimental
+} // namespace std
+
+ */
+
+#include <experimental/__config>
+#include <new>
+#include <type_traits>
+#include <functional>
+#include <memory> // for hash<T*>
+#include <cstddef>
+#include <cassert>
+#include <__debug>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+#ifndef __cpp_coroutines
+# if defined(_LIBCPP_WARNING)
+ _LIBCPP_WARNING("<experimental/coroutine> cannot be used with this compiler")
+# else
+# warning <experimental/coroutine> cannot be used with this compiler
+# endif
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES
+
+template <class _Tp, class = void>
+struct __coroutine_traits_sfinae {};
+
+template <class _Tp>
+struct __coroutine_traits_sfinae<
+ _Tp, typename __void_t<typename _Tp::promise_type>::type>
+{
+ using promise_type = typename _Tp::promise_type;
+};
+
+template <typename _Ret, typename... _Args>
+struct _LIBCPP_TEMPLATE_VIS coroutine_traits
+ : public __coroutine_traits_sfinae<_Ret>
+{
+};
+
+template <typename Promise = void>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle;
+
+#if defined(__cpp_coroutines)
+
+template <>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle<void> {
+public:
+ _LIBCPP_ALWAYS_INLINE
+ constexpr coroutine_handle() noexcept : __handle_(nullptr) {}
+
+ _LIBCPP_ALWAYS_INLINE
+ constexpr coroutine_handle(nullptr_t) noexcept : __handle_(nullptr) {}
+
+ _LIBCPP_ALWAYS_INLINE
+ coroutine_handle& operator=(nullptr_t) noexcept {
+ __handle_ = nullptr;
+ return *this;
+ }
+
+ _LIBCPP_ALWAYS_INLINE
+ constexpr void* address() const noexcept { return __handle_; }
+
+ _LIBCPP_ALWAYS_INLINE
+ constexpr explicit operator bool() const noexcept { return __handle_; }
+
+ _LIBCPP_ALWAYS_INLINE
+ void operator()() const { resume(); }
+
+ _LIBCPP_ALWAYS_INLINE
+ void resume() const {
+ _LIBCPP_ASSERT(__is_suspended(),
+ "resume() can only be called on suspended coroutines");
+ _LIBCPP_ASSERT(!done(),
+ "resume() has undefined behavior when the coroutine is done");
+ __builtin_coro_resume(__handle_);
+ }
+
+ _LIBCPP_ALWAYS_INLINE
+ void destroy() const {
+ _LIBCPP_ASSERT(__is_suspended(),
+ "destroy() can only be called on suspended coroutines");
+ __builtin_coro_destroy(__handle_);
+ }
+
+ _LIBCPP_ALWAYS_INLINE
+ bool done() const {
+ _LIBCPP_ASSERT(__is_suspended(),
+ "done() can only be called on suspended coroutines");
+ return __builtin_coro_done(__handle_);
+ }
+
+public:
+ _LIBCPP_ALWAYS_INLINE
+ static coroutine_handle from_address(void* __addr) noexcept {
+ coroutine_handle __tmp;
+ __tmp.__handle_ = __addr;
+ return __tmp;
+ }
+
+private:
+ bool __is_suspended() const noexcept {
+ // FIXME actually implement a check for if the coro is suspended.
+ return __handle_;
+ }
+
+ template <class _PromiseT> friend class coroutine_handle;
+ void* __handle_;
+};
+
+// 18.11.2.7 comparison operators:
+inline _LIBCPP_ALWAYS_INLINE
+bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return __x.address() == __y.address();
+}
+inline _LIBCPP_ALWAYS_INLINE
+bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return !(__x == __y);
+}
+inline _LIBCPP_ALWAYS_INLINE
+bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return less<void*>()(__x.address(), __y.address());
+}
+inline _LIBCPP_ALWAYS_INLINE
+bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return __y < __x;
+}
+inline _LIBCPP_ALWAYS_INLINE
+bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return !(__x > __y);
+}
+inline _LIBCPP_ALWAYS_INLINE
+bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept {
+ return !(__x < __y);
+}
+
+template <typename _Promise>
+class _LIBCPP_TEMPLATE_VIS coroutine_handle : public coroutine_handle<> {
+ using _Base = coroutine_handle<>;
+public:
+ // 18.11.2.1 construct/reset
+ using coroutine_handle<>::coroutine_handle;
+
+ _LIBCPP_INLINE_VISIBILITY
+ coroutine_handle& operator=(nullptr_t) noexcept {
+ _Base::operator=(nullptr);
+ return *this;
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ _Promise& promise() {
+ return *reinterpret_cast<_Promise*>(
+ __builtin_coro_promise(this->__handle_, alignof(_Promise), false));
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
+ _Promise const& promise() const {
+ return *reinterpret_cast<_Promise const*>(
+ __builtin_coro_promise(this->__handle_, alignof(_Promise), false));
+ }
+
+public:
+ _LIBCPP_ALWAYS_INLINE
+ static coroutine_handle from_address(void* __addr) noexcept {
+ coroutine_handle __tmp;
+ __tmp.__handle_ = __addr;
+ return __tmp;
+ }
+
+ _LIBCPP_ALWAYS_INLINE
+ static coroutine_handle from_promise(_Promise& __promise) noexcept {
+ coroutine_handle __tmp;
+ __tmp.__handle_ = __builtin_coro_promise(_VSTD::addressof(__promise),
+ alignof(_Promise), true);
+ return __tmp;
+ }
+};
+
+#endif // defined(__cpp_coroutines)
+
+struct _LIBCPP_TYPE_VIS suspend_never {
+ _LIBCPP_ALWAYS_INLINE
+ bool await_ready() const noexcept { return true; }
+ _LIBCPP_ALWAYS_INLINE
+ void await_suspend(coroutine_handle<>) const noexcept {}
+ _LIBCPP_ALWAYS_INLINE
+ void await_resume() const noexcept {}
+};
+
+struct _LIBCPP_TYPE_VIS suspend_always {
+ _LIBCPP_ALWAYS_INLINE
+ bool await_ready() const noexcept { return false; }
+ _LIBCPP_ALWAYS_INLINE
+ void await_suspend(coroutine_handle<>) const noexcept {}
+ _LIBCPP_ALWAYS_INLINE
+ void await_resume() const noexcept {}
+};
+
+_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp>
+struct hash<_VSTD_CORO::coroutine_handle<_Tp> > {
+ using __arg_type = _VSTD_CORO::coroutine_handle<_Tp>;
+ _LIBCPP_INLINE_VISIBILITY
+ size_t operator()(__arg_type const& __v) const noexcept
+ {return hash<void*>{}(__v.address());}
+};
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */
diff --git a/include/module.modulemap b/include/module.modulemap
index c354cae1e..737ef9a7d 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/test/libcxx/double_include.sh.cpp b/test/libcxx/double_include.sh.cpp
index 46dfc999b..0a9e9fcfa 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/version.sh.cpp b/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp
new file mode 100644
index 000000000..229ce10dd
--- /dev/null
+++ b/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp
@@ -0,0 +1,25 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+// REQUIRES: fcoroutines-ts
+
+// RUN: %build -fcoroutines-ts
+// RUN: %run
+
+#include <experimental/coroutine>
+
+#ifndef _LIBCPP_VERSION
+#error _LIBCPP_VERSION must be defined
+#endif
+
+int main()
+{
+}
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 000000000..7eae2d0e9
--- /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
+ int dummy = 42;
+ C c = C::from_address(&dummy);
+ assert(c.address() == &dummy);
+ assert(bool(c) == true);
+ }
+}
+
+int main()
+{
+ do_test<coro::coroutine_handle<>>();
+ do_test<coro::coroutine_handle<int>>();
+}
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 000000000..05c3f230e
--- /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 000000000..7b3bcc394
--- /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 000000000..48c3ca50c
--- /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 000000000..9e7fb5b2f
--- /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 000000000..961253fb7
--- /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 000000000..b5b8c1002
--- /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);
+ }
+ {
+ int dummy = 42;
+ C c = C::from_address(&dummy);
+ assert(c.address() == &dummy);
+ }
+}
+
+int main()
+{
+ do_test<coro::coroutine_handle<>>();
+ do_test<coro::coroutine_handle<int>>();
+}
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 000000000..356e1704f
--- /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);
+ }
+ {
+ int dummy = 42;
+ C c = C::from_address(&dummy);
+ assert(c.address() == &dummy);
+ }
+}
+
+int main()
+{
+ do_test<coro::coroutine_handle<>>();
+ do_test<coro::coroutine_handle<int>>();
+}
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 000000000..5f66b3e11
--- /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 000000000..290aaa382
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp
@@ -0,0 +1,54 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+// REQUIRES: fcoroutines-ts
+
+// RUN: %build -fcoroutines-ts
+// RUN: %run
+
+// <experimental/coroutine>
+
+// template <class Promise>
+// struct coroutine_handle<Promise>;
+
+// Promise& promise()
+// Promise const& promise() const
+
+#include <experimental/coroutine>
+#include <type_traits>
+#include <memory>
+#include <utility>
+#include <cstdint>
+#include <cassert>
+
+#include "test_macros.h"
+
+namespace coro = std::experimental;
+
+template <class Promise>
+void do_test(coro::coroutine_handle<Promise>&& H) {
+
+ // FIXME Add a runtime test
+ {
+ ASSERT_SAME_TYPE(decltype(H.promise()), Promise&);
+ ASSERT_NOT_NOEXCEPT(H.promise());
+ }
+ {
+ auto const& CH = H;
+ ASSERT_SAME_TYPE(decltype(CH.promise()), Promise const&);
+ ASSERT_NOT_NOEXCEPT(CH.promise());
+ }
+}
+
+int main()
+{
+ do_test(coro::coroutine_handle<int>{});
+}
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 000000000..49899e8f7
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.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;
+
+// void destroy() const
+
+#include <experimental/coroutine>
+#include <type_traits>
+#include <memory>
+#include <utility>
+#include <cstdint>
+#include <cassert>
+
+#include "test_macros.h"
+
+namespace coro = std::experimental;
+
+template <class Promise>
+void do_test(coro::coroutine_handle<Promise> const& H) {
+ // FIXME Add a runtime test
+ {
+ ASSERT_SAME_TYPE(decltype(H.destroy()), void);
+ ASSERT_NOT_NOEXCEPT(H.destroy());
+ }
+}
+
+int main()
+{
+ do_test(coro::coroutine_handle<>{});
+ do_test(coro::coroutine_handle<int>{});
+}
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 000000000..dc3beb4b7
--- /dev/null
+++ b/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp
@@ -0,0 +1,51 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+// REQUIRES: fcoroutines-ts
+
+// RUN: %build -fcoroutines-ts
+// RUN: %run
+
+// <experimental/coroutine>
+
+// template <class Promise = void>
+// struct coroutine_handle;
+
+// void operator()() const
+// void resume() const
+
+#include <experimental/coroutine>
+#include <type_traits>
+#include <memory>
+#include <utility>
+#include <cstdint>
+#include <cassert>
+
+#include "test_macros.h"
+
+namespace coro = std::experimental;
+
+template <class Promise>
+void do_test(coro::coroutine_handle<Promise> const& H) {
+ // FIXME Add a runtime test
+ {
+ ASSERT_SAME_TYPE(decltype(H.resume()), void);
+ ASSERT_SAME_TYPE(decltype(H()), void);
+ ASSERT_NOT_NOEXCEPT(H.resume());
+ ASSERT_NOT_NOEXCEPT(H());
+ }
+}
+
+int main()
+{
+ do_test(coro::coroutine_handle<>{});
+ do_test(coro::coroutine_handle<int>{});
+}
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 000000000..945304a46
--- /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 000000000..c1d3b818d
--- /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 000000000..1987f68e7
--- /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 000000000..72e0ac024
--- /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/includes.sh.cpp b/test/std/experimental/language.support/support.coroutines/includes.sh.cpp
new file mode 100644
index 000000000..f9d8a5722
--- /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/support/test_macros.h b/test/support/test_macros.h
index 6b573d40f..637686284 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/utils/libcxx/test/config.py b/utils/libcxx/test/config.py
index 2118f9c7e..2b89a1cd2 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,10 @@ class Configuration(object):
self.cxx.flags += ['-g', '--coverage']
self.cxx.compile_flags += ['-O0']
+ def configure_coroutines(self):
+ if self.cxx.hasCompileFlag('-fcoroutines-ts'):
+ self.config.available_features.add('fcoroutines-ts')
+
def configure_modules(self):
modules_flags = ['-fmodules']
if platform.system() != 'Darwin':