diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2017-05-29 16:26:10 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2017-05-29 16:26:10 +0000 |
commit | b276b1db48faa7328575ab722fe3bc340623f025 (patch) | |
tree | 9e4ba424f754c3f05e409ae647fa358031d97617 /test/std/experimental | |
parent | d1bd27794dfbc317e27d1ec63b338115cbf194ba (diff) |
Notes
Diffstat (limited to 'test/std/experimental')
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; + +} |