forked from OSchip/llvm-project
[clang] More informative mixed namespace diagnostics
First, let's check we get a TemplateDecl, before complaining about where it might have been found. Second, if it came from an unexpected place, show where that location is. Reviewed By: ChuanqiXu Differential Revision: https://reviews.llvm.org/D116164
This commit is contained in:
parent
b1a333f0fe
commit
d4f09786e0
|
@ -1740,30 +1740,38 @@ ClassTemplateDecl *Sema::lookupCoroutineTraits(SourceLocation KwLoc,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!InStd) {
|
||||
// Found only in std::experimental.
|
||||
Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
|
||||
<< "coroutine_traits";
|
||||
} else if (InExp) {
|
||||
// Found in std and std::experimental.
|
||||
Diag(KwLoc,
|
||||
diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
|
||||
Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
|
||||
<< "coroutine_traits";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Prefer ::std to std::experimental.
|
||||
auto &Result = InStd ? ResStd : ResExp;
|
||||
CoroTraitsNamespaceCache = InStd ? StdSpace : ExpSpace;
|
||||
|
||||
// coroutine_traits is required to be a class template.
|
||||
if (!(StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>())) {
|
||||
StdCoroutineTraitsCache = Result.getAsSingle<ClassTemplateDecl>();
|
||||
if (!StdCoroutineTraitsCache) {
|
||||
Result.suppressDiagnostics();
|
||||
NamedDecl *Found = *Result.begin();
|
||||
Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (InExp) {
|
||||
// Found in std::experimental
|
||||
Diag(KwLoc, diag::warn_deprecated_coroutine_namespace)
|
||||
<< "coroutine_traits";
|
||||
ResExp.suppressDiagnostics();
|
||||
auto *Found = *ResExp.begin();
|
||||
Diag(Found->getLocation(), diag::note_entity_declared_at) << Found;
|
||||
|
||||
if (InStd) {
|
||||
// Also found in std
|
||||
Diag(KwLoc,
|
||||
diag::err_mixed_use_std_and_experimental_namespace_for_coroutine);
|
||||
Diag(StdCoroutineTraitsCache->getLocation(),
|
||||
diag::note_entity_declared_at)
|
||||
<< StdCoroutineTraitsCache;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
Namespace = CoroTraitsNamespaceCache;
|
||||
return StdCoroutineTraitsCache;
|
||||
|
|
|
@ -53,6 +53,7 @@ MyForLoopArrayAwaiter g() {
|
|||
for co_await (auto i : arr) {} // expected-warning {{support for std::experimental::coroutine_traits will be removed}}
|
||||
// expected-error@-1 {{call to deleted member function 'await_transform'}}
|
||||
// expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
|
||||
// expected-note@Inputs/std-coroutine-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
}
|
||||
|
||||
struct ForLoopAwaiterBadBeginTransform {
|
||||
|
|
|
@ -40,6 +40,7 @@ VoidTagReturnValue test() {
|
|||
object x = {};
|
||||
try {
|
||||
co_return {}; // expected-warning {{support for std::experimental::coroutine_traits will be removed}}
|
||||
// expected-note@Inputs/std-coroutine-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,7 @@ template <typename... T>
|
|||
struct std::experimental::coroutine_traits<int, T...> { using promise_type = promise_int; };
|
||||
|
||||
void test0() { co_await a; } // expected-warning {{support for std::experimental::coroutine_traits will be removed}}
|
||||
// expected-note@Inputs/std-coroutine-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
float test1() { co_await a; }
|
||||
|
||||
int test2() {
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace std {
|
|||
namespace experimental {
|
||||
template <class Ret, typename... T>
|
||||
struct coroutine_traits { using promise_type = typename Ret::promise_type; };
|
||||
// expected-note@-1{{declared here}}
|
||||
|
||||
template <class Promise = void>
|
||||
struct coroutine_handle {
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
|
||||
|
||||
#include "Inputs/std-coroutine-exp-namespace.h"
|
||||
#include "Inputs/std-coroutine.h"
|
||||
#include "Inputs/std-coroutine.h" // Second
|
||||
|
||||
struct my_awaitable {
|
||||
bool await_ready() noexcept;
|
||||
|
@ -25,4 +25,6 @@ struct std::coroutine_traits<void> { 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-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
// expected-note@Inputs/std-coroutine.h:8 {{'coroutine_traits' declared here}}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
// This file is to test the mixed use of `std::experimental::coroutine_traits` and `std::coroutine_traits`
|
||||
// which is similar to coroutine-mixed-exp-namesapce. This file tests the relative order of
|
||||
// which is similar to coroutine-mixed-exp-namespace. This file tests the relative order of
|
||||
// included header wouldn't affect the diagnostic messages.
|
||||
// RUN: %clang_cc1 -verify -std=c++20 -fsyntax-only %s
|
||||
|
||||
#include "Inputs/std-coroutine.h" // First
|
||||
#include "Inputs/std-coroutine-exp-namespace.h"
|
||||
#include "Inputs/std-coroutine.h"
|
||||
|
||||
struct my_awaitable {
|
||||
bool await_ready() noexcept;
|
||||
|
@ -26,4 +26,6 @@ struct std::coroutine_traits<void> { 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-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
// expected-note@Inputs/std-coroutine.h:8 {{'coroutine_traits' declared here}}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
|
|||
|
||||
template <class Ret, class... Args>
|
||||
struct coroutine_traits : public traits_sfinae_base<Ret> {};
|
||||
// expected-note@-1{{declared here}}
|
||||
} // namespace std::experimental
|
||||
|
||||
struct suspend_never {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// RUN: %clang_cc1 -std=c++1z -fcoroutines-ts -verify %s -fcxx-exceptions -fexceptions -triple x86_64-windows-msvc -fms-extensions
|
||||
namespace std::experimental {
|
||||
template <typename... T> struct coroutine_traits;
|
||||
// expected-note@-1{{declared here}}
|
||||
|
||||
template <class Promise = void> struct coroutine_handle {
|
||||
coroutine_handle() = default;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
namespace std {
|
||||
namespace experimental {
|
||||
template <typename... T>
|
||||
struct coroutine_traits {
|
||||
struct coroutine_traits { // expected-note{{declared here}}
|
||||
struct promise_type {};
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ struct std::experimental::coroutine_traits<void, T...> { using promise_type = pr
|
|||
#ifndef DISABLE_WARNING
|
||||
void test0() { // expected-warning {{'promise_void' is required to declare the member 'unhandled_exception()' when exceptions are enabled}}
|
||||
co_return; // expected-warning {{support for std::experimental::coroutine_traits will be removed}}
|
||||
// expected-note@Inputs/std-coroutine-exp-namespace.h:8 {{'coroutine_traits' declared here}}
|
||||
}
|
||||
#else
|
||||
void test0() { // expected-no-diagnostics
|
||||
|
|
|
@ -32,6 +32,7 @@ struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
|
|||
|
||||
template <class Ret, class... Args>
|
||||
struct coroutine_traits : public traits_sfinae_base<Ret> {};
|
||||
// expected-note@-1{{declared here}}
|
||||
} // namespace std::experimental
|
||||
|
||||
struct suspend_never {
|
||||
|
|
|
@ -45,6 +45,7 @@ struct traits_sfinae_base<T, void_t<typename T::promise_type>> {
|
|||
|
||||
template <class Ret, class... Args>
|
||||
struct coroutine_traits : public traits_sfinae_base<Ret> {};
|
||||
// expected-note@-1{{declared here}}
|
||||
} // namespace experimental
|
||||
} // namespace std
|
||||
|
||||
|
|
Loading…
Reference in New Issue