[clang] 2ac339e - [C++20] [Coroutines] Warn for deprecated form 'for co_await'

Chuanqi Xu via cfe-commits cfe-commits at lists.llvm.org
Mon Nov 22 00:09:04 PST 2021


Author: Chuanqi Xu
Date: 2021-11-22T15:57:57+08:00
New Revision: 2ac339ef5f0feca2abe2b8a1720839c58184166c

URL: https://github.com/llvm/llvm-project/commit/2ac339ef5f0feca2abe2b8a1720839c58184166c
DIFF: https://github.com/llvm/llvm-project/commit/2ac339ef5f0feca2abe2b8a1720839c58184166c.diff

LOG: [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.

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 85d373845c818..68e0da72550e2 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -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,

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 1bc2e8b0c7ef5..92e877074ad3d 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -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 {

diff  --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index bb8718671bb0e..292ab03e8614f 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -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.

diff  --git a/clang/test/SemaCXX/co_await-range-for.cpp b/clang/test/SemaCXX/co_await-range-for.cpp
index e43f55a3434d1..a3feffab4bb27 100644
--- a/clang/test/SemaCXX/co_await-range-for.cpp
+++ b/clang/test/SemaCXX/co_await-range-for.cpp
@@ -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 at -1 {{call to deleted member function 'await_transform'}}
   // expected-note at -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 at -1 {{call to deleted member function 'await_transform'}}
   // expected-note at -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 at -1 {{call to deleted member function 'await_transform'}}
   // expected-note at -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 at -1 {{overload resolution selected deleted operator 'co_await'}}
   // expected-note at -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 at -1 {{overload resolution selected deleted operator 'co_await'}}
   // expected-note at -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 at -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 at -1 {{no member named 'await_ready' in 'CoawaitTag<Iter<int>, false>'}}
 }
 template ForLoopAwaiterCoawaitLookup test_coawait_lookup(int); // expected-note {{requested here}}


        


More information about the cfe-commits mailing list