diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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 " diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -1761,8 +1761,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(), diff --git a/clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp b/clang/test/SemaCXX/coroutine-mixed3-exp-namespace.cpp new file mode 100644 --- /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 --- /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}} +}