[C++20] [Coroutines] Warn for deprecated form 'for co_await'

The form 'for co_await' is part of CoroutineTS instead of C++20.
So if we detected the use of 'for co_await' in C++20, we should emit
a warning at least.
This commit is contained in:
Chuanqi Xu 2021-11-22 15:53:51 +08:00
parent 6a3958247a
commit 2ac339ef5f
4 changed files with 16 additions and 8 deletions

View File

@ -56,7 +56,9 @@ def CoroutineMissingUnhandledException :
DiagGroup<"coroutine-missing-unhandled-exception">;
def DeprecatedExperimentalCoroutine :
DiagGroup<"deprecated-experimental-coroutine">;
def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedExperimentalCoroutine]>;
def DeprecatedCoroutine :
DiagGroup<"deprecated-coroutine", [DeprecatedExperimentalCoroutine]>;
def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException, DeprecatedCoroutine]>;
def ObjCBoolConstantConversion : DiagGroup<"objc-bool-constant-conversion">;
def ConstantConversion : DiagGroup<"constant-conversion",
[BitFieldConstantConversion,

View File

@ -1548,6 +1548,9 @@ def note_meant_to_use_typename : Note<
let CategoryName = "Coroutines Issue" in {
def err_for_co_await_not_range_for : Error<
"'co_await' modifier can only be applied to range-based for loop">;
def warn_deprecated_for_co_await : Warning<
"'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated">,
InGroup<DeprecatedCoroutine>;
}
let CategoryName = "Concepts Issue" in {

View File

@ -2108,6 +2108,9 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) {
CoawaitLoc = SourceLocation();
}
if (CoawaitLoc.isValid() && getLangOpts().CPlusPlus20)
Diag(CoawaitLoc, diag::warn_deprecated_for_co_await);
// We need to perform most of the semantic analysis for a C++0x for-range
// statememt before parsing the body, in order to be able to deduce the type
// of an auto-typed loop variable.

View File

@ -50,7 +50,7 @@ struct MyForLoopArrayAwaiter {
};
MyForLoopArrayAwaiter g() {
int arr[10] = {0};
for co_await(auto i : arr) {}
for co_await(auto i : arr) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{call to deleted member function 'await_transform'}}
// expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
}
@ -72,14 +72,14 @@ struct ForLoopAwaiterBadBeginTransform {
};
ForLoopAwaiterBadBeginTransform bad_begin() {
Range<int> R;
for co_await(auto i : R) {}
for co_await(auto i : R) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{call to deleted member function 'await_transform'}}
// expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
}
template <class Dummy>
ForLoopAwaiterBadBeginTransform bad_begin_template(Dummy) {
Range<Dummy> R;
for co_await(auto i : R) {}
for co_await(auto i : R) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{call to deleted member function 'await_transform'}}
// expected-note@-2 {{'await_transform' implicitly required by 'co_await' here}}
}
@ -106,7 +106,7 @@ struct ForLoopAwaiterBadIncTransform {
};
ForLoopAwaiterBadIncTransform bad_inc_transform() {
Range<float> R;
for co_await(auto i : R) {}
for co_await(auto i : R) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{overload resolution selected deleted operator 'co_await'}}
// expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<float>'}}
}
@ -114,7 +114,7 @@ ForLoopAwaiterBadIncTransform bad_inc_transform() {
template <class Dummy>
ForLoopAwaiterBadIncTransform bad_inc_transform_template(Dummy) {
Range<Dummy> R;
for co_await(auto i : R) {}
for co_await(auto i : R) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{overload resolution selected deleted operator 'co_await'}}
// expected-note@-2 {{in implicit call to 'operator++' for iterator of type 'Range<long>'}}
}
@ -125,7 +125,7 @@ template ForLoopAwaiterBadIncTransform bad_inc_transform_template(long); // expe
template <class T>
constexpr void never_instant(T) {
static_assert(sizeof(T) != sizeof(T), "function should not be instantiated");
for co_await(auto i : foo(T{})) {}
for co_await(auto i : foo(T{})) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{'co_await' cannot be used in a constexpr function}}
}
@ -149,7 +149,7 @@ using NS::ForLoopAwaiterCoawaitLookup;
template <class T>
ForLoopAwaiterCoawaitLookup test_coawait_lookup(T) {
Range<T> R;
for co_await(auto i : R) {}
for co_await(auto i : R) {} // expected-warning {{'for co_await' belongs to CoroutineTS instead of C++20, which is deprecated}}
// expected-error@-1 {{no member named 'await_ready' in 'CoawaitTag<Iter<int>, false>'}}
}
template ForLoopAwaiterCoawaitLookup test_coawait_lookup(int); // expected-note {{requested here}}