Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11047,7 +11047,7 @@ "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 " Index: clang/lib/Sema/SemaCoroutine.cpp =================================================================== --- clang/lib/Sema/SemaCoroutine.cpp +++ clang/lib/Sema/SemaCoroutine.cpp @@ -1705,8 +1705,9 @@ 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(), Index: clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s + +#include "Inputs/std-coroutine.h" + +namespace std::experimental { +// expected-note@+1{{declared here}} +using std::coroutine_handle; +using std::coroutine_traits; +} // 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}} +} Index: clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp =================================================================== --- /dev/null +++ clang/test/SemaCXX/coroutine-mixed4-exp-namespace.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -verify=expected,declared -std=c++20 -fsyntax-only %s + +#include "Inputs/std-coroutine.h" // First + +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}} +}