summaryrefslogtreecommitdiff
path: root/test/std/experimental
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 /test/std/experimental
parentd1bd27794dfbc317e27d1ec63b338115cbf194ba (diff)
Notes
Diffstat (limited to 'test/std/experimental')
-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
25 files changed, 1876 insertions, 0 deletions
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;
+
+}