From: Eric Fiselier Date: Thu, 25 May 2017 04:36:24 +0000 (+0000) Subject: Add X-Git-Tag: llvmorg-5.0.0-rc1~4330 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3ca9185073ef365ac7e4e027af4c939bc27cacc3;p=platform%2Fupstream%2Fllvm.git Add This patch adds the library portions of the coroutines PDTS, which should now be supported by Clang. llvm-svn: 303836 --- diff --git a/libcxx/CMakeLists.txt b/libcxx/CMakeLists.txt index 8c25a0a..33d888b 100644 --- a/libcxx/CMakeLists.txt +++ b/libcxx/CMakeLists.txt @@ -452,6 +452,11 @@ add_compile_flags_if_supported(-nostdinc++) # the dylib when get ODR used by another function. add_compile_flags_if_supported(-fvisibility-inlines-hidden) +if (LIBCXX_CONFIGURE_IDE) + # This simply allows IDE to process + add_compile_flags_if_supported(-fcoroutines-ts) +endif() + # Let the library headers know they are currently being used to build the # library. add_definitions(-D_LIBCPP_BUILDING_LIBRARY) diff --git a/libcxx/include/experimental/__config b/libcxx/include/experimental/__config index 9a7bbe8..37f88c1 100644 --- a/libcxx/include/experimental/__config +++ b/libcxx/include/experimental/__config @@ -44,6 +44,13 @@ #define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_FILESYSTEM \ } } _LIBCPP_END_NAMESPACE_EXPERIMENTAL +#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES \ + _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace coroutines_v1 { + +#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES \ + } _LIBCPP_END_NAMESPACE_EXPERIMENTAL + +#define _VSTD_CORO _VSTD_EXPERIMENTAL::coroutines_v1 #define _VSTD_FS ::std::experimental::filesystem::v1 diff --git a/libcxx/include/experimental/coroutine b/libcxx/include/experimental/coroutine new file mode 100644 index 0000000..208a4d2 --- /dev/null +++ b/libcxx/include/experimental/coroutine @@ -0,0 +1,260 @@ +// -*- C++ -*- +//===----------------------------- coroutine -----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP_EXPERIMENTAL_COROUTINE +#define _LIBCPP_EXPERIMENTAL_COROUTINE + +/** + experimental/coroutine synopsis + +// C++next + +namespace std { +namespace experimental { +inline namespace coroutines_v1 { + + // 18.11.1 coroutine traits +template +class coroutine_traits; +// 18.11.2 coroutine handle +template +class coroutine_handle; +// 18.11.2.7 comparison operators: +bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; +bool operator!=(coroutine_handle<> x, coroutine_handle<> y) noexcept; +bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept; +bool operator<=(coroutine_handle<> x, coroutine_handle<> y) noexcept; +bool operator>=(coroutine_handle<> x, coroutine_handle<> y) noexcept; +bool operator>(coroutine_handle<> x, coroutine_handle<> y) noexcept; +// 18.11.3 trivial awaitables +struct suspend_never; +struct suspend_always; +// 18.11.2.8 hash support: +template struct hash; +template struct hash>; + +} // namespace coroutines_v1 +} // namespace experimental +} // namespace std + + */ + +#include +#include +#include +#include +#include // for hash +#include +#include +#include <__debug> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +#ifndef __cpp_coroutines +# if defined(_LIBCPP_WARNING) + _LIBCPP_WARNING(" cannot be used with this compiler") +# else +# warning cannot be used with this compiler +# endif +#endif + +_LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL_COROUTINES + +template +struct __coroutine_traits_sfinae {}; + +template +struct __coroutine_traits_sfinae< + _Tp, typename __void_t::type> +{ + using promise_type = typename _Tp::promise_type; +}; + +template +struct _LIBCPP_TEMPLATE_VIS coroutine_traits + : public __coroutine_traits_sfinae<_Ret> +{ +}; + +template +class _LIBCPP_TEMPLATE_VIS coroutine_handle; + +#if defined(__cpp_coroutines) + +template <> +class _LIBCPP_TEMPLATE_VIS coroutine_handle { +public: + _LIBCPP_ALWAYS_INLINE + constexpr coroutine_handle() noexcept : __handle_(nullptr) {} + + _LIBCPP_ALWAYS_INLINE + constexpr coroutine_handle(nullptr_t) noexcept : __handle_(nullptr) {} + + _LIBCPP_ALWAYS_INLINE + coroutine_handle& operator=(nullptr_t) noexcept { + __handle_ = nullptr; + return *this; + } + + _LIBCPP_ALWAYS_INLINE + constexpr void* address() const noexcept { return __handle_; } + + _LIBCPP_ALWAYS_INLINE + constexpr explicit operator bool() const noexcept { return __handle_; } + + _LIBCPP_ALWAYS_INLINE + void operator()() const { resume(); } + + _LIBCPP_ALWAYS_INLINE + void resume() const { + _LIBCPP_ASSERT(__is_suspended(), + "resume() can only be called on suspended coroutines"); + _LIBCPP_ASSERT(!done(), + "resume() has undefined behavior when the coroutine is done"); + __builtin_coro_resume(__handle_); + } + + _LIBCPP_ALWAYS_INLINE + void destroy() const { + _LIBCPP_ASSERT(__is_suspended(), + "destroy() can only be called on suspended coroutines"); + __builtin_coro_destroy(__handle_); + } + + _LIBCPP_ALWAYS_INLINE + bool done() const { + _LIBCPP_ASSERT(__is_suspended(), + "done() can only be called on suspended coroutines"); + return __builtin_coro_done(__handle_); + } + +public: + _LIBCPP_ALWAYS_INLINE + static coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + +private: + bool __is_suspended() const noexcept { + // FIXME actually implement a check for if the coro is suspended. + return __handle_; + } + + template friend class coroutine_handle; + void* __handle_; +}; + +// 18.11.2.7 comparison operators: +inline _LIBCPP_ALWAYS_INLINE +bool operator==(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return __x.address() == __y.address(); +} +inline _LIBCPP_ALWAYS_INLINE +bool operator!=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return !(__x == __y); +} +inline _LIBCPP_ALWAYS_INLINE +bool operator<(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return less()(__x.address(), __y.address()); +} +inline _LIBCPP_ALWAYS_INLINE +bool operator>(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return __y < __x; +} +inline _LIBCPP_ALWAYS_INLINE +bool operator<=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return !(__x > __y); +} +inline _LIBCPP_ALWAYS_INLINE +bool operator>=(coroutine_handle<> __x, coroutine_handle<> __y) noexcept { + return !(__x < __y); +} + +template +class _LIBCPP_TEMPLATE_VIS coroutine_handle : public coroutine_handle<> { + using _Base = coroutine_handle<>; +public: + // 18.11.2.1 construct/reset + using coroutine_handle<>::coroutine_handle; + + _LIBCPP_INLINE_VISIBILITY + coroutine_handle& operator=(nullptr_t) noexcept { + _Base::operator=(nullptr); + return *this; + } + + _LIBCPP_INLINE_VISIBILITY + _Promise& promise() { + return *reinterpret_cast<_Promise*>( + __builtin_coro_promise(this->__handle_, alignof(_Promise), false)); + } + + _LIBCPP_INLINE_VISIBILITY + _Promise const& promise() const { + return *reinterpret_cast<_Promise const*>( + __builtin_coro_promise(this->__handle_, alignof(_Promise), false)); + } + +public: + _LIBCPP_ALWAYS_INLINE + static coroutine_handle from_address(void* __addr) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __addr; + return __tmp; + } + + _LIBCPP_ALWAYS_INLINE + static coroutine_handle from_promise(_Promise& __promise) noexcept { + coroutine_handle __tmp; + __tmp.__handle_ = __builtin_coro_promise(_VSTD::addressof(__promise), + alignof(_Promise), true); + return __tmp; + } +}; + +#endif // defined(__cpp_coroutines) + +struct _LIBCPP_TYPE_VIS suspend_never { + _LIBCPP_ALWAYS_INLINE + bool await_ready() const noexcept { return true; } + _LIBCPP_ALWAYS_INLINE + void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_ALWAYS_INLINE + void await_resume() const noexcept {} +}; + +struct _LIBCPP_TYPE_VIS suspend_always { + _LIBCPP_ALWAYS_INLINE + bool await_ready() const noexcept { return false; } + _LIBCPP_ALWAYS_INLINE + void await_suspend(coroutine_handle<>) const noexcept {} + _LIBCPP_ALWAYS_INLINE + void await_resume() const noexcept {} +}; + +_LIBCPP_END_NAMESPACE_EXPERIMENTAL_COROUTINES + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct hash<_VSTD_CORO::coroutine_handle<_Tp> > { + using __arg_type = _VSTD_CORO::coroutine_handle<_Tp>; + _LIBCPP_INLINE_VISIBILITY + size_t operator()(__arg_type const& __v) const noexcept + {return hash{}(__v.address());} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif /* _LIBCPP_EXPERIMENTAL_COROUTINE */ diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index c354cae..737ef9a 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -501,6 +501,10 @@ module std [system] { header "experimental/chrono" export * } + module coroutine { + header "experimental/coroutine" + export * + } module deque { header "experimental/deque" export * diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp index 46dfc99..0a9e9fc 100644 --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -137,6 +137,9 @@ #include #include #include +#if defined(__cpp_coroutines) +#include +#endif #include #include #include diff --git a/libcxx/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp b/libcxx/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp new file mode 100644 index 0000000..229ce10 --- /dev/null +++ b/libcxx/test/libcxx/experimental/language.support/support.coroutines/version.sh.cpp @@ -0,0 +1,25 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// REQUIRES: fcoroutines-ts + +// RUN: %build -fcoroutines-ts +// RUN: %run + +#include + +#ifndef _LIBCPP_VERSION +#error _LIBCPP_VERSION must be defined +#endif + +int main() +{ +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.capacity/operator_bool.sh.cpp new file mode 100644 index 0000000..7eae2d0 --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// constexpr explicit operator bool() const noexcept + +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test() { + static_assert(std::is_nothrow_constructible::value, ""); + static_assert(!std::is_convertible::value, ""); + { + constexpr C c; ((void)c); + static_assert(bool(c) == false, ""); + } + { // null case + const C c = {}; ((void)c); + ASSERT_NOEXCEPT(bool(c)); + if (c) + assert(false); + else + assert(true); + assert(c.address() == nullptr); + assert(bool(c) == false); + } + { // non-null case + int dummy = 42; + C c = C::from_address(&dummy); + assert(c.address() == &dummy); + assert(bool(c) == true); + } +} + +int main() +{ + do_test>(); + do_test>(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/equal_comp.sh.cpp new file mode 100644 index 0000000..05c3f23 --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// bool operator==(coroutine_handle<>, coroutine_handle<>) noexcept +// bool operator!=(coroutine_handle<>, coroutine_handle<>) noexcept + +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(uintptr_t LHSVal, uintptr_t RHSVal) { + const C LHS = C::from_address(reinterpret_cast(LHSVal)); + const C RHS = C::from_address(reinterpret_cast(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 const TestCases[] = { + {0, 0}, + {16, 16}, + {0, 16}, + {16, 0} + }; + for (auto& TC : TestCases) { + do_test>(TC.first, TC.second); + do_test>(TC.first, TC.second); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.compare/less_comp.sh.cpp new file mode 100644 index 0000000..7b3bcc3 --- /dev/null +++ b/libcxx/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 + +// + +// template +// 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 +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(uintptr_t LHSVal, uintptr_t RHSVal) { + const C LHS = C::from_address(reinterpret_cast(LHSVal)); + const C RHS = C::from_address(reinterpret_cast(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 const TestCases[] = { + {0, 0}, + {16, 16}, + {0, 16}, + {16, 0} + }; + for (auto& TC : TestCases) { + do_test>(TC.first, TC.second); + do_test>(TC.first, TC.second); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.completion/done.sh.cpp new file mode 100644 index 0000000..48c3ca5 --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// bool done() const + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(coro::coroutine_handle 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{}); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/assign.sh.cpp new file mode 100644 index 0000000..9e7fb5b --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// coroutine_handle& operator=(nullptr_t) noexcept + +#include +#include +#include + +namespace coro = std::experimental; + +template +void do_test() { + int dummy = 42; + void* dummy_h = &dummy; + { + C c; ((void)c); + static_assert(std::is_nothrow_assignable::value, ""); + static_assert(!std::is_assignable::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>(); + do_test>(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.con/construct.sh.cpp new file mode 100644 index 0000000..961253f --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// constexpr coroutine_handle() noexcept +// constexpr coroutine_handle(nullptr_t) noexcept + +#include +#include +#include + +namespace coro = std::experimental; + +template +void do_test() { + { + constexpr C c; + static_assert(std::is_nothrow_default_constructible::value, ""); + static_assert(c.address() == nullptr, ""); + } + { + constexpr C c(nullptr); + static_assert(std::is_nothrow_constructible::value, ""); + static_assert(c.address() == nullptr, ""); + } + { + C c; + assert(c.address() == nullptr); + } + { + C c(nullptr); + assert(c.address() == nullptr); + } +} + +int main() +{ + do_test>(); + do_test>(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/address.sh.cpp new file mode 100644 index 0000000..b5b8c10 --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// constexpr void* address() const noexcept + +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test() { + { + constexpr C c; ((void)c); + static_assert(c.address() == nullptr, ""); + } + { + const C c = {}; ((void)c); + ASSERT_NOEXCEPT(c.address()); + ASSERT_SAME_TYPE(decltype(c.address()), void*); + assert(c.address() == nullptr); + } + { + int dummy = 42; + C c = C::from_address(&dummy); + assert(c.address() == &dummy); + } +} + +int main() +{ + do_test>(); + do_test>(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.export/from_address.sh.cpp new file mode 100644 index 0000000..356e170 --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// static coroutine_handle from_address(void*) noexcept + +#include +#include +#include + +namespace coro = std::experimental; + +template +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::value, ""); + assert(c.address() == nullptr); + } + { + int dummy = 42; + C c = C::from_address(&dummy); + assert(c.address() == &dummy); + } +} + +int main() +{ + do_test>(); + do_test>(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.hash/hash.sh.cpp new file mode 100644 index 0000000..5f66b3e --- /dev/null +++ b/libcxx/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 + +// + +// template +// struct coroutine_handle; + +// namespace std { +// template struct hash>; +// } + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(uintptr_t LHSVal, uintptr_t RHSVal) { + const size_t ExpectLHS = std::hash{}(reinterpret_cast(LHSVal)); + const size_t ExpectRHS = std::hash{}(reinterpret_cast(RHSVal)); + const C LHS = C::from_address(reinterpret_cast(LHSVal)); + const C RHS = C::from_address(reinterpret_cast(RHSVal)); + const std::hash 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{}(LHS)); + } +} + +int main() +{ + std::pair const TestCases[] = { + {0, 0}, + {0, 8}, + {8, 8}, + {8, 16} + }; + for (auto& TC : TestCases) { + do_test>(TC.first, TC.second); + do_test>(TC.first, TC.second); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp new file mode 100644 index 0000000..290aaa3 --- /dev/null +++ b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.prom/promise.sh.cpp @@ -0,0 +1,54 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// REQUIRES: fcoroutines-ts + +// RUN: %build -fcoroutines-ts +// RUN: %run + +// + +// template +// struct coroutine_handle; + +// Promise& promise() +// Promise const& promise() const + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(coro::coroutine_handle&& H) { + + // FIXME Add a runtime test + { + ASSERT_SAME_TYPE(decltype(H.promise()), Promise&); + ASSERT_NOT_NOEXCEPT(H.promise()); + } + { + auto const& CH = H; + ASSERT_SAME_TYPE(decltype(CH.promise()), Promise const&); + ASSERT_NOT_NOEXCEPT(CH.promise()); + } +} + +int main() +{ + do_test(coro::coroutine_handle{}); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp new file mode 100644 index 0000000..49899e8 --- /dev/null +++ b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/destroy.sh.cpp @@ -0,0 +1,48 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// REQUIRES: fcoroutines-ts + +// RUN: %build -fcoroutines-ts +// RUN: %run + +// + +// template +// struct coroutine_handle; + +// void destroy() const + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(coro::coroutine_handle const& H) { + // FIXME Add a runtime test + { + ASSERT_SAME_TYPE(decltype(H.destroy()), void); + ASSERT_NOT_NOEXCEPT(H.destroy()); + } +} + +int main() +{ + do_test(coro::coroutine_handle<>{}); + do_test(coro::coroutine_handle{}); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp new file mode 100644 index 0000000..dc3beb4 --- /dev/null +++ b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/coroutine.handle.resumption/resume.sh.cpp @@ -0,0 +1,51 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11 +// REQUIRES: fcoroutines-ts + +// RUN: %build -fcoroutines-ts +// RUN: %run + +// + +// template +// struct coroutine_handle; + +// void operator()() const +// void resume() const + +#include +#include +#include +#include +#include +#include + +#include "test_macros.h" + +namespace coro = std::experimental; + +template +void do_test(coro::coroutine_handle const& H) { + // FIXME Add a runtime test + { + ASSERT_SAME_TYPE(decltype(H.resume()), void); + ASSERT_SAME_TYPE(decltype(H()), void); + ASSERT_NOT_NOEXCEPT(H.resume()); + ASSERT_NOT_NOEXCEPT(H()); + } +} + +int main() +{ + do_test(coro::coroutine_handle<>{}); + do_test(coro::coroutine_handle{}); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.handle/void_handle.sh.cpp new file mode 100644 index 0000000..945304a --- /dev/null +++ b/libcxx/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 + +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 + struct coroutine_traits<::B, Args...> { + using promise_type = B*; + }; + template <> + struct coroutine_traits<::C> { + using promise_type = void; + }; +}} + +template +void check_type() { + using P = typename coro::coroutine_traits::promise_type ; + static_assert(std::is_same::value, ""); +}; + +int main() +{ + check_type(); + check_type(); + check_type(); + check_type(); +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.traits/promise_type.sh.cpp new file mode 100644 index 0000000..c1d3b81 --- /dev/null +++ b/libcxx/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 + +namespace coro = std::experimental; + +template +constexpr bool has_promise_type(int) { return true; } +template +constexpr bool has_promise_type(long) { return false; } +template +constexpr bool has_promise_type() { return has_promise_type(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 + struct coroutine_traits<::B, Args...> { + using promise_type = B*; + }; + template <> + struct coroutine_traits<::C> { + using promise_type = void; + }; +}} + +template +void check_type() { + using Traits = coro::coroutine_traits; + static_assert(has_promise_type(), ""); + static_assert(std::is_same::value, ""); +} + +template +void check_no_type() { + using Traits = coro::coroutine_traits; + static_assert(!has_promise_type(), ""); +} + +int main() +{ + { + check_type(); + check_type(); + check_type(); + check_type(); + } + { + check_no_type(); + check_no_type(); + check_no_type(); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_always.sh.cpp new file mode 100644 index 0000000..1987f68 --- /dev/null +++ b/libcxx/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 +#include +#include + +#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::value, ""); + assert(s.await_ready() == false); + assert(cs.await_ready() == false); + } + { + LIBCPP_STATIC_ASSERT(noexcept(s.await_suspend(h)), ""); + static_assert(std::is_same::value, ""); + s.await_suspend(h); + cs.await_suspend(h); + } + { + LIBCPP_STATIC_ASSERT(noexcept(s.await_resume()), ""); + static_assert(std::is_same::value, ""); + s.await_resume(); + cs.await_resume(); + } + { + static_assert(std::is_nothrow_default_constructible::value, ""); + static_assert(std::is_nothrow_copy_constructible::value, ""); + static_assert(std::is_nothrow_move_constructible::value, ""); + static_assert(std::is_nothrow_copy_assignable::value, ""); + static_assert(std::is_nothrow_move_assignable::value, ""); + static_assert(std::is_trivially_copyable::value, ""); + static_assert(check_suspend_constexpr(), ""); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/coroutine.trivial.awaitables/suspend_never.sh.cpp new file mode 100644 index 0000000..72e0ac0 --- /dev/null +++ b/libcxx/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 +#include +#include + +#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::value, ""); + assert(s.await_ready() == true); + assert(cs.await_ready() == true); + } + { + LIBCPP_STATIC_ASSERT(noexcept(s.await_suspend(h)), ""); + static_assert(std::is_same::value, ""); + s.await_suspend(h); + cs.await_suspend(h); + } + { + LIBCPP_STATIC_ASSERT(noexcept(s.await_resume()), ""); + static_assert(std::is_same::value, ""); + s.await_resume(); + cs.await_resume(); + } + { + static_assert(std::is_nothrow_default_constructible::value, ""); + static_assert(std::is_nothrow_copy_constructible::value, ""); + static_assert(std::is_nothrow_move_constructible::value, ""); + static_assert(std::is_nothrow_copy_assignable::value, ""); + static_assert(std::is_nothrow_move_assignable::value, ""); + static_assert(std::is_trivially_copyable::value, ""); + static_assert(check_suspend_constexpr(), ""); + } +} diff --git a/libcxx/test/std/experimental/language.support/support.coroutines/includes.sh.cpp b/libcxx/test/std/experimental/language.support/support.coroutines/includes.sh.cpp new file mode 100644 index 0000000..f9d8a57 --- /dev/null +++ b/libcxx/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 + +// + +// Test that includes + +#include + + + +int main(){ + // std::nothrow is not implicitly defined by the compiler when the include is + // missing, unlike other parts of . Therefore we use std::nothrow to + // test for #include + (void)std::nothrow; + +} diff --git a/libcxx/test/support/test_macros.h b/libcxx/test/support/test_macros.h index 6b573d4..6376862 100644 --- a/libcxx/test/support/test_macros.h +++ b/libcxx/test/support/test_macros.h @@ -154,6 +154,12 @@ #define TEST_NORETURN [[noreturn]] #endif +#if defined(_LIBCPP_SAFE_STATIC) +#define TEST_SAFE_STATIC _LIBCPP_SAFE_STATIC +#else +#define TEST_SAFE_STATIC +#endif + #if TEST_STD_VER < 11 #define ASSERT_NOEXCEPT(...) #define ASSERT_NOT_NOEXCEPT(...) diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py index 2118f9c..2b89a1c 100644 --- a/libcxx/utils/libcxx/test/config.py +++ b/libcxx/utils/libcxx/test/config.py @@ -142,6 +142,7 @@ class Configuration(object): self.configure_sanitizer() self.configure_coverage() self.configure_modules() + self.configure_coroutines() self.configure_substitutions() self.configure_features() @@ -954,6 +955,10 @@ class Configuration(object): self.cxx.flags += ['-g', '--coverage'] self.cxx.compile_flags += ['-O0'] + def configure_coroutines(self): + if self.cxx.hasCompileFlag('-fcoroutines-ts'): + self.config.available_features.add('fcoroutines-ts') + def configure_modules(self): modules_flags = ['-fmodules'] if platform.system() != 'Darwin':