diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1337,6 +1337,16 @@ +Matcher<Stmt>coawaitExprMatcher<CoawaitExpr>... +
Matches co_await expressions.
+
+Given
+  co_await 1;
+coawaitExpr()
+  matches 'co_await 1'
+
+ + Matcher<Stmt>compoundLiteralExprMatcher<CompoundLiteralExpr>...
Matches compound (i.e. non-scalar) literals
 
@@ -1383,6 +1393,26 @@
 
+Matcher<Stmt>coreturnStmtMatcher<CoreturnStmt>... +
Matches co_return statements.
+
+Given
+  while (true) { co_return; }
+coreturnStmt()
+  matches 'co_return'
+
+ + +Matcher<Stmt>coyieldExprMatcher<CoyieldExpr>... +
Matches co_yield expressions.
+
+Given
+  co_yield 1;
+coyieldExpr()
+  matches 'co_yield 1'
+
+ + Matcher<Stmt>cudaKernelCallExprMatcher<CUDAKernelCallExpr>...
Matches CUDA kernel call expression.
 
@@ -1698,6 +1728,11 @@
 
+Matcher<Stmt>dependentCoawaitExprMatcher<DependentCoawaitExpr>... +
Matches co_await expressions where the type of the promise is dependent
+
+ + Matcher<Stmt>designatedInitExprMatcher<DesignatedInitExpr>...
Matches C99 designated initializer expressions [C99 6.7.8].
 
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2162,6 +2162,17 @@
 extern const internal::VariadicDynCastAllOfMatcher
     continueStmt;
 
+/// Matches co_return statements.
+///
+/// Given
+/// \code
+///   while (true) { co_return; }
+/// \endcode
+/// coreturnStmt()
+///   matches 'co_return'
+extern const internal::VariadicDynCastAllOfMatcher
+    coreturnStmt;
+
 /// Matches return statements.
 ///
 /// Given
@@ -2379,6 +2390,30 @@
 extern const internal::VariadicDynCastAllOfMatcher
     compoundLiteralExpr;
 
+/// Matches co_await expressions.
+///
+/// Given
+/// \code
+///   co_await 1;
+/// \endcode
+/// coawaitExpr()
+///   matches 'co_await 1'
+extern const internal::VariadicDynCastAllOfMatcher
+    coawaitExpr;
+/// Matches co_await expressions where the type of the promise is dependent
+extern const internal::VariadicDynCastAllOfMatcher
+    dependentCoawaitExpr;
+/// Matches co_yield expressions.
+///
+/// Given
+/// \code
+///   co_yield 1;
+/// \endcode
+/// coyieldExpr()
+///   matches 'co_yield 1'
+extern const internal::VariadicDynCastAllOfMatcher
+    coyieldExpr;
+
 /// Matches nullptr literal.
 extern const internal::VariadicDynCastAllOfMatcher
     cxxNullPtrLiteralExpr;
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -883,6 +883,7 @@
 const internal::VariadicDynCastAllOfMatcher doStmt;
 const internal::VariadicDynCastAllOfMatcher breakStmt;
 const internal::VariadicDynCastAllOfMatcher continueStmt;
+const internal::VariadicDynCastAllOfMatcher coreturnStmt;
 const internal::VariadicDynCastAllOfMatcher returnStmt;
 const internal::VariadicDynCastAllOfMatcher gotoStmt;
 const internal::VariadicDynCastAllOfMatcher labelStmt;
@@ -915,6 +916,12 @@
 const internal::VariadicDynCastAllOfMatcher
     cxxNullPtrLiteralExpr;
 const internal::VariadicDynCastAllOfMatcher chooseExpr;
+const internal::VariadicDynCastAllOfMatcher
+    coawaitExpr;
+const internal::VariadicDynCastAllOfMatcher
+    dependentCoawaitExpr;
+const internal::VariadicDynCastAllOfMatcher
+    coyieldExpr;
 const internal::VariadicDynCastAllOfMatcher gnuNullExpr;
 const internal::VariadicDynCastAllOfMatcher
     genericSelectionExpr;
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -166,11 +166,14 @@
   REGISTER_MATCHER(complexType);
   REGISTER_MATCHER(compoundLiteralExpr);
   REGISTER_MATCHER(compoundStmt);
+  REGISTER_MATCHER(coawaitExpr);
   REGISTER_MATCHER(conditionalOperator);
   REGISTER_MATCHER(constantArrayType);
   REGISTER_MATCHER(constantExpr);
   REGISTER_MATCHER(containsDeclaration);
   REGISTER_MATCHER(continueStmt);
+  REGISTER_MATCHER(coreturnStmt);
+  REGISTER_MATCHER(coyieldExpr);
   REGISTER_MATCHER(cudaKernelCallExpr);
   REGISTER_MATCHER(cxxBindTemporaryExpr);
   REGISTER_MATCHER(cxxBoolLiteral);
@@ -214,6 +217,7 @@
   REGISTER_MATCHER(decltypeType);
   REGISTER_MATCHER(deducedTemplateSpecializationType);
   REGISTER_MATCHER(defaultStmt);
+  REGISTER_MATCHER(dependentCoawaitExpr);
   REGISTER_MATCHER(dependentSizedArrayType);
   REGISTER_MATCHER(designatedInitExpr);
   REGISTER_MATCHER(designatorCountIs);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -510,6 +510,83 @@
                                   varDecl(hasName("lPtrDecay"))))))));
 }
 
+TEST(Matcher, MatchesCoroutine) {
+  FileContentMappings M;
+  M.push_back(std::make_pair("/coro_header", R"cpp(
+namespace std {
+namespace experimental {
+
+template 
+struct void_t_imp {
+  using type = void;
+};
+template 
+using void_t = typename void_t_imp::type;
+
+template 
+struct traits_sfinae_base {};
+
+template 
+struct traits_sfinae_base> {
+  using promise_type = typename T::promise_type;
+};
+
+template 
+struct coroutine_traits : public traits_sfinae_base {};
+}}  // namespace std::experimental
+struct awaitable {
+  bool await_ready() noexcept;
+  template 
+  void await_suspend(F) noexcept;
+  void await_resume() noexcept;
+} a;
+struct promise {
+  void get_return_object();
+  awaitable initial_suspend();
+  awaitable final_suspend() noexcept;
+  awaitable yield_value(int); // expected-note 2{{candidate}}
+  void return_value(int); // expected-note 2{{here}}
+  void unhandled_exception();
+};
+template 
+struct std::experimental::coroutine_traits { using promise_type = promise; };
+namespace std {
+namespace experimental {
+template 
+struct coroutine_handle {
+  static coroutine_handle from_address(void *) noexcept;
+};
+}} // namespace std::experimental
+)cpp"));
+  StringRef CoReturnCode = R"cpp(
+#include 
+void check_match_co_return() {
+  co_return 1;
+}
+)cpp";
+  EXPECT_TRUE(matchesConditionally(CoReturnCode, 
+                                   coreturnStmt(isExpansionInMainFile()), 
+                                   true, {"-std=c++20", "-I/"}, M));
+  StringRef CoAwaitCode = R"cpp(
+#include 
+void check_match_co_await() {
+  co_await a;
+}
+)cpp";
+  EXPECT_TRUE(matchesConditionally(CoAwaitCode, 
+                                   coawaitExpr(isExpansionInMainFile()), 
+                                   true, {"-std=c++20", "-I/"}, M));
+  StringRef CoYieldCode = R"cpp(
+#include 
+void check_match_co_yield() {
+  co_yield 1.0;
+}
+)cpp";
+  EXPECT_TRUE(matchesConditionally(CoYieldCode, 
+                                   coyieldExpr(isExpansionInMainFile()), 
+                                   true, {"-std=c++20", "-I/"}, M));
+}
+
 TEST(Matcher, isClassMessage) {
   EXPECT_TRUE(matchesObjC(
       "@interface NSString +(NSString *) stringWithFormat; @end "