1349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #ifndef _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H
10349cc55cSDimitry Andric #define _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H
11349cc55cSDimitry Andric 
12349cc55cSDimitry Andric #include <__config>
13349cc55cSDimitry Andric #include <__coroutine/coroutine_handle.h>
14349cc55cSDimitry Andric 
15349cc55cSDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16349cc55cSDimitry Andric #  pragma GCC system_header
17349cc55cSDimitry Andric #endif
18349cc55cSDimitry Andric 
1906c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 20
20349cc55cSDimitry Andric 
21349cc55cSDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD
22349cc55cSDimitry Andric 
2304eeddc0SDimitry Andric #  if __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)
2404eeddc0SDimitry Andric 
25349cc55cSDimitry Andric // [coroutine.noop]
26349cc55cSDimitry Andric // [coroutine.promise.noop]
27349cc55cSDimitry Andric struct noop_coroutine_promise {};
28349cc55cSDimitry Andric 
29349cc55cSDimitry Andric // [coroutine.handle.noop]
30349cc55cSDimitry Andric template <>
31349cc55cSDimitry Andric struct _LIBCPP_TEMPLATE_VIS coroutine_handle<noop_coroutine_promise> {
32349cc55cSDimitry Andric public:
33349cc55cSDimitry Andric   // [coroutine.handle.noop.conv], conversion
34*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr operator coroutine_handle<>() const noexcept {
35349cc55cSDimitry Andric     return coroutine_handle<>::from_address(address());
36349cc55cSDimitry Andric   }
37349cc55cSDimitry Andric 
38349cc55cSDimitry Andric   // [coroutine.handle.noop.observers], observers
39*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr explicit operator bool() const noexcept { return true; }
40*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr bool done() const noexcept { return false; }
41349cc55cSDimitry Andric 
42349cc55cSDimitry Andric   // [coroutine.handle.noop.resumption], resumption
43*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void operator()() const noexcept {}
44*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void resume() const noexcept {}
45*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void destroy() const noexcept {}
46349cc55cSDimitry Andric 
47349cc55cSDimitry Andric   // [coroutine.handle.noop.promise], promise access
48*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI noop_coroutine_promise& promise() const noexcept {
49349cc55cSDimitry Andric     return *static_cast<noop_coroutine_promise*>(
50349cc55cSDimitry Andric         __builtin_coro_promise(this->__handle_, alignof(noop_coroutine_promise), false));
51349cc55cSDimitry Andric   }
52349cc55cSDimitry Andric 
53349cc55cSDimitry Andric   // [coroutine.handle.noop.address], address
54*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI constexpr void* address() const noexcept { return __handle_; }
55349cc55cSDimitry Andric 
56349cc55cSDimitry Andric private:
57*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI friend coroutine_handle<noop_coroutine_promise> noop_coroutine() noexcept;
58349cc55cSDimitry Andric 
5904eeddc0SDimitry Andric #    if __has_builtin(__builtin_coro_noop)
60*cb14a3feSDimitry Andric   _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept { this->__handle_ = __builtin_coro_noop(); }
61349cc55cSDimitry Andric 
62349cc55cSDimitry Andric   void* __handle_ = nullptr;
6304eeddc0SDimitry Andric 
6404eeddc0SDimitry Andric #    elif defined(_LIBCPP_COMPILER_GCC)
6504eeddc0SDimitry Andric   // GCC doesn't implement __builtin_coro_noop().
6604eeddc0SDimitry Andric   // Construct the coroutine frame manually instead.
6704eeddc0SDimitry Andric   struct __noop_coroutine_frame_ty_ {
6804eeddc0SDimitry Andric     static void __dummy_resume_destroy_func() {}
6904eeddc0SDimitry Andric 
7004eeddc0SDimitry Andric     void (*__resume_)()  = __dummy_resume_destroy_func;
7104eeddc0SDimitry Andric     void (*__destroy_)() = __dummy_resume_destroy_func;
7204eeddc0SDimitry Andric     struct noop_coroutine_promise __promise_;
7304eeddc0SDimitry Andric   };
7404eeddc0SDimitry Andric 
7504eeddc0SDimitry Andric   static __noop_coroutine_frame_ty_ __noop_coroutine_frame_;
7604eeddc0SDimitry Andric 
7704eeddc0SDimitry Andric   void* __handle_ = &__noop_coroutine_frame_;
7804eeddc0SDimitry Andric 
7904eeddc0SDimitry Andric   _LIBCPP_HIDE_FROM_ABI coroutine_handle() noexcept = default;
8004eeddc0SDimitry Andric 
8104eeddc0SDimitry Andric #    endif // __has_builtin(__builtin_coro_noop)
82349cc55cSDimitry Andric };
83349cc55cSDimitry Andric 
84349cc55cSDimitry Andric using noop_coroutine_handle = coroutine_handle<noop_coroutine_promise>;
85349cc55cSDimitry Andric 
8604eeddc0SDimitry Andric #    if defined(_LIBCPP_COMPILER_GCC)
87*cb14a3feSDimitry Andric inline noop_coroutine_handle::__noop_coroutine_frame_ty_ noop_coroutine_handle::__noop_coroutine_frame_{};
8804eeddc0SDimitry Andric #    endif
8904eeddc0SDimitry Andric 
90349cc55cSDimitry Andric // [coroutine.noop.coroutine]
91*cb14a3feSDimitry Andric inline _LIBCPP_HIDE_FROM_ABI noop_coroutine_handle noop_coroutine() noexcept { return noop_coroutine_handle(); }
92349cc55cSDimitry Andric 
9304eeddc0SDimitry Andric #  endif // __has_builtin(__builtin_coro_noop) || defined(_LIBCPP_COMPILER_GCC)
94349cc55cSDimitry Andric 
95349cc55cSDimitry Andric _LIBCPP_END_NAMESPACE_STD
96349cc55cSDimitry Andric 
9706c3fb27SDimitry Andric #endif // __LIBCPP_STD_VER >= 20
98349cc55cSDimitry Andric 
99349cc55cSDimitry Andric #endif // _LIBCPP___COROUTINE_NOOP_COROUTINE_HANDLE_H
100