[C++20] [Coroutines] Warn for deprecated form 'for co_await'
authorChuanqi Xu <yedeng.yd@linux.alibaba.com>
Mon, 22 Nov 2021 07:53:51 +0000 (15:53 +0800)
committerChuanqi Xu <yedeng.yd@linux.alibaba.com>
Mon, 22 Nov 2021 07:57:57 +0000 (15:57 +0800)
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.

clang/include/clang/Basic/DiagnosticGroups.td
clang/include/clang/Basic/DiagnosticParseKinds.td
clang/lib/Parse/ParseStmt.cpp
clang/test/SemaCXX/co_await-range-for.cpp

index 85d3738..68e0da7 100644 (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,
index 1bc2e8b..92e8770 100644 (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 {
index bb87186..292ab03 100644 (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.
index e43f55a..a3feffa 100644 (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}}