Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Downlevel standard coroutine support #1730

Merged
merged 4 commits into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 29 additions & 4 deletions stl/inc/coroutine
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,19 @@

#ifdef _RESUMABLE_FUNCTIONS_SUPPORTED
#pragma message("The contents of <coroutine> are not available with /await.")
#pragma message("Remove /await for standard coroutines or use <experimental/coroutine> for legacy /await support.")
#pragma message("Remove /await or use /await:strict for standard coroutines.")
#pragma message("Use <experimental/coroutine> for legacy /await support.")
#else // ^^^ /await ^^^ / vvv no /await vvv
#ifndef __cpp_lib_coroutine
#pragma message("The contents of <coroutine> are available only with C++20 or later.")
#else // ^^^ __cpp_lib_coroutine not defined / __cpp_lib_coroutine defined vvv
#pragma message("The contents of <coroutine> are available only with C++20 or later or /await:strict.")
#else // ^^^ <coroutine> is not available / <coroutine> is available vvv
#ifndef _ALLOW_COROUTINE_ABI_MISMATCH
#pragma detect_mismatch("_COROUTINE_ABI", "2")
#endif // _ALLOW_COROUTINE_ABI_MISMATCH

#if _HAS_CXX20
#include <compare>
#endif // _HAS_CXX20
#include <type_traits>

#pragma pack(push, _CRT_PACKING)
Expand Down Expand Up @@ -156,6 +159,7 @@ _NODISCARD constexpr bool operator==(const coroutine_handle<> _Left, const corou
return _Left.address() == _Right.address();
}

#if _HAS_CXX20
_NODISCARD constexpr strong_ordering operator<=>(
const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
#ifdef __cpp_lib_concepts
Expand All @@ -164,6 +168,27 @@ _NODISCARD constexpr strong_ordering operator<=>(
return _Left.address() <=> _Right.address();
#endif // __cpp_lib_concepts
}
#else // ^^^ <=> exists / <=> does not exist vvv
_NODISCARD constexpr bool operator!=(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
return !(_Left == _Right);
}

_NODISCARD constexpr bool operator<(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
return less<void*>{}(_Left.address(), _Right.address());
}

_NODISCARD constexpr bool operator>(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
return _Right < _Left;
}

_NODISCARD constexpr bool operator<=(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
return !(_Left > _Right);
}

_NODISCARD constexpr bool operator>=(const coroutine_handle<> _Left, const coroutine_handle<> _Right) noexcept {
return !(_Left < _Right);
}
#endif // _HAS_CXX20

template <class _Promise>
struct hash<coroutine_handle<_Promise>> {
Expand Down Expand Up @@ -246,7 +271,7 @@ _STL_RESTORE_CLANG_WARNINGS
#pragma warning(pop)
#pragma pack(pop)

#endif // __cpp_lib_coroutine
#endif // <coroutine> is available
#endif // _RESUMABLE_FUNCTIONS_SUPPORTED
#endif // _STL_COMPILER_PREPROCESSOR
#endif // _COROUTINE_
8 changes: 4 additions & 4 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -1220,10 +1220,6 @@
#define __cpp_lib_constexpr_vector 201907L
#endif // defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__)

#ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support
#define __cpp_lib_coroutine 201902L
#endif // __cpp_impl_coroutine

#define __cpp_lib_destroying_delete 201806L
#define __cpp_lib_endian 201907L
#define __cpp_lib_erase_if 202002L
Expand Down Expand Up @@ -1296,6 +1292,10 @@
#define __cpp_lib_shared_ptr_arrays 201611L // P0497R0 Fixing shared_ptr For Arrays
#endif // _HAS_CXX20

#if defined(__cpp_impl_coroutine) || defined(_DOWNLEVEL_COROUTINES_SUPPORTED) // TRANSITION, Clang coroutine support
Copy link
Member

@CaseyCarter CaseyCarter Mar 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Late feedback: We should remove the TRANSITION comment. Now that this is outside of _HAS_CXX20, this condition is permanent. I hate to make a PR for a single comment cleanup. @stl (Sorry!) @StephanTLavavej, do you have a "miscellaneous cleanups" branch laying around you could add this change to, or should I start one of my own?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had recorded a todo about the matching comment being out of date (too small to reset testing), I’ll add this to that list, and fix it when we’re done with deadlines.

#define __cpp_lib_coroutine 201902L
#endif // __cpp_impl_coroutine

// EXPERIMENTAL
#define __cpp_lib_experimental_erase_if 201411L
#define __cpp_lib_experimental_filesystem 201406L
Expand Down
19 changes: 18 additions & 1 deletion tests/std/tests/P0912R5_coroutine/env.lst
Original file line number Diff line number Diff line change
@@ -1,4 +1,21 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
RUNALL_INCLUDE ..\prefix.lst
RUNALL_CROSSLIST
PM_CL="/EHsc /MD /await:strict /std:c++14"
PM_CL="/EHsc /MD /await:strict /std:c++14 /permissive-"
PM_CL="/EHsc /MTd /await:strict /std:c++14 /permissive- /Zc:preprocessor"
PM_CL="/EHsc /MD /await:strict /std:c++14 /permissive- /analyze:only /analyze:autolog-"
PM_CL="/EHsc /MD /await:strict /std:c++17"
PM_CL="/EHsc /MD /await:strict /std:c++17 /permissive-"
PM_CL="/EHsc /MTd /await:strict /std:c++17 /permissive- /Zc:preprocessor"
PM_CL="/EHsc /MD /await:strict /std:c++17 /permissive- /analyze:only /analyze:autolog-"
PM_CL="/EHsc /MD /std:c++latest /permissive"
PM_CL="/EHsc /MD /std:c++latest /permissive-"
PM_CL="/EHsc /MTd /std:c++latest /permissive- /Zc:preprocessor"
PM_CL="/EHsc /MD /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="/BE /c /EHsc /MD /std:c++latest /permissive-"
PM_CL="/BE /c /EHsc /MTd /std:c++latest /permissive-"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MD /std:c++latest /permissive-"
PM_COMPILER="clang-cl" PM_CL="-fno-ms-compatibility -fno-delayed-template-parsing /EHsc /MTd /std:c++latest /permissive-"
29 changes: 16 additions & 13 deletions tests/std/tests/P0912R5_coroutine/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <exception>
using namespace std;

#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__)

int g_tasks_destroyed{0};

struct Task {
Expand All @@ -33,7 +35,8 @@ struct Task {
void await_resume() noexcept {}

coroutine_handle<> await_suspend(coroutine_handle<Promise> h) noexcept {
if (auto& pre = h.promise().previous; pre) {
auto& pre = h.promise().previous;
if (pre) {
return pre; // resume awaiting coroutine
}

Expand Down Expand Up @@ -97,50 +100,50 @@ Task triangular_number(const int n) {

void test_noop_handle() { // Validate noop_coroutine_handle
const noop_coroutine_handle noop = noop_coroutine();
static_assert(noexcept(noop_coroutine()));
STATIC_ASSERT(noexcept(noop_coroutine()));

const coroutine_handle<> as_void = noop;
static_assert(noexcept(static_cast<coroutine_handle<>>(noop_coroutine())));
STATIC_ASSERT(noexcept(static_cast<coroutine_handle<>>(noop_coroutine())));

assert(noop);
assert(as_void);
static_assert(noexcept(static_cast<bool>(noop)));
static_assert(noexcept(static_cast<bool>(as_void)));
STATIC_ASSERT(noexcept(static_cast<bool>(noop)));
STATIC_ASSERT(noexcept(static_cast<bool>(as_void)));

assert(!noop.done());
assert(!as_void.done());
static_assert(noexcept(noop.done()));
static_assert(noexcept(as_void.done()));
STATIC_ASSERT(noexcept(noop.done()));
STATIC_ASSERT(noexcept(as_void.done()));

assert(noop);
assert(as_void);
noop();
as_void();
static_assert(noexcept(noop()));
STATIC_ASSERT(noexcept(noop()));

assert(noop);
assert(as_void);
noop.resume();
as_void.resume();
static_assert(noexcept(noop.resume()));
STATIC_ASSERT(noexcept(noop.resume()));

assert(noop);
assert(as_void);
noop.destroy();
as_void.destroy();
static_assert(noexcept(noop.destroy()));
STATIC_ASSERT(noexcept(noop.destroy()));

assert(noop);
assert(as_void);
assert(&noop.promise() != nullptr);
static_assert(noexcept(noop.promise()));
STATIC_ASSERT(noexcept(noop.promise()));

assert(noop);
assert(as_void);
assert(noop.address() != nullptr);
assert(noop.address() == as_void.address());
static_assert(noexcept(noop.address()));
static_assert(noexcept(as_void.address()));
STATIC_ASSERT(noexcept(noop.address()));
STATIC_ASSERT(noexcept(as_void.address()));
}

int main() {
Expand Down