From b50fea47b6c454581fce89af359f3afe5154986c Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Sat, 25 Dec 2021 13:30:42 -0500 Subject: [PATCH] [clang] Allow using std::coroutine_traits in std::experimental This is that diff I was aiming for. When transitioning code from coroutines-ts to c++20, it can be useful to add a using declaration to std::experimental pointing to std::coroutine_traits. This permits that use by checking whether lookup in std::experimentl finds a different decl to lookup in std. You still get a warning about std::experimental::coroutine_traits being a thing, just not an error. Reviewed By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D115943 --- .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaCoroutine.cpp | 5 +-- .../coroutine-mixed3-exp-namespace.cpp | 30 +++++++++++++++++ .../coroutine-mixed4-exp-namespace.cpp | 32 +++++++++++++++++++ 4 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp create mode 100644 clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8ef9195944d5..afc63d480627 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11047,7 +11047,7 @@ def warn_deprecated_coroutine_namespace : Warning< "use std::%0 instead">, InGroup; def err_mixed_use_std_and_experimental_namespace_for_coroutine : Error< - "mixed use of std and std::experimental namespaces for " + "conflicting mixed use of std and std::experimental namespaces for " "coroutine components">; def err_implicit_coroutine_std_nothrow_type_not_found : Error< "std::nothrow was not found; include before defining a coroutine which " diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 3a6d9f0b9f26..f5f78c02e370 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1761,8 +1761,9 @@ ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc, auto *Found = *ResExp.begin(); Diag(Found->getLocation(), diag::note_entity_declared_at) << Found; - if (InStd) { - // Also found in std + if (InStd && + StdCoroutineTraitsCache != ResExp.getAsSingle()) { + // Also found something different in std Diag(KwLoc, diag::err_mixed_use_std_and_experimental_namespace_for_coroutine); Diag(StdCoroutineTraitsCache->getLocation(), diff --git a/clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp b/clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp new file mode 100644 index 000000000000..533f9d78e278 --- /dev/null +++ b/clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +#include "Inputs/std-coroutine.h" + +namespace std::experimental { +using std::coroutine_handle; +using std::coroutine_traits; // expected-note{{declared here}} +} // namespace std::experimental + +struct my_awaitable { + bool await_ready() noexcept; + void await_suspend(std::coroutine_handle<> coro) noexcept; + void await_resume() noexcept; +}; + +struct promise_void { + void get_return_object(); + my_awaitable initial_suspend(); + my_awaitable final_suspend() noexcept; + void return_void(); + void unhandled_exception(); +}; + +template <> +struct std::coroutine_traits { using promise_type = promise_void; }; + +void test() { + co_return; + // expected-warning@-1{{support for std::experimental::coroutine_traits will be removed}} +} diff --git a/clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp b/clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp new file mode 100644 index 000000000000..715282dd2df8 --- /dev/null +++ b/clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +#include "Inputs/std-coroutine.h" + +namespace std::experimental { +// expected-note@+1{{declared here}} +template using coroutine_traits = std::coroutine_traits; +using std::coroutine_handle; +} // namespace std::experimental + +struct my_awaitable { + bool await_ready() noexcept; + void await_suspend(std::experimental::coroutine_handle<> coro) noexcept; + void await_resume() noexcept; +}; + +struct promise_void { + void get_return_object(); + my_awaitable initial_suspend(); + my_awaitable final_suspend() noexcept; + void return_void(); + void unhandled_exception(); +}; + +template <> +struct std::coroutine_traits { using promise_type = promise_void; }; + +void test() { + co_return; // expected-error {{mixed use of std and std::experimental namespaces for coroutine components}} + // expected-warning@-1{{support for std::experimental::coroutine_traits will be removed}} + // expected-note@Inputs/std-coroutine.h:8 {{'coroutine_traits' declared here}} +}