Index: clang/docs/LibASTMatchersReference.html
===================================================================
--- clang/docs/LibASTMatchersReference.html
+++ clang/docs/LibASTMatchersReference.html
@@ -1331,6 +1331,16 @@
+
Matcher<Stmt> | coawaitExpr | Matcher<CoawaitExpr>... |
+Matches co_await expressions.
+
+Given
+ co_await 1;
+coawaitExpr()
+ matches 'co_await 1'
+ |
+
+
Matcher<Stmt> | compoundLiteralExpr | Matcher<CompoundLiteralExpr>... |
Matches compound (i.e. non-scalar) literals
@@ -1377,6 +1387,26 @@
|
+Matcher<Stmt> | coreturnStmt | Matcher<CoreturnStmt>... |
+Matches co_return statements.
+
+Given
+ while (true) { co_return; }
+coreturnStmt()
+ matches 'co_return'
+ |
+
+
+Matcher<Stmt> | coyieldExpr | Matcher<CoyieldExpr>... |
+Matches co_yield expressions.
+
+Given
+ co_yield 1;
+coyieldExpr()
+ matches 'co_yield 1'
+ |
+
+
Matcher<Stmt> | cudaKernelCallExpr | Matcher<CUDAKernelCallExpr>... |
Matches CUDA kernel call expression.
@@ -1692,6 +1722,11 @@
|
+Matcher<Stmt> | dependentCoawaitExpr | Matcher<DependentCoawaitExpr>... |
+Matches co_await expressions where the type of the promise is dependent
+ |
+
+
Matcher<Stmt> | designatedInitExpr | Matcher<DesignatedInitExpr>... |
Matches C99 designated initializer expressions [C99 6.7.8].
@@ -7146,7 +7181,8 @@
f = 42;
}
The matcher:
- decompositionDecl(hasBinding(0, bindingDecl(hasName("f").bind("fBinding"))))
+ decompositionDecl(hasBinding(0,
+ bindingDecl(hasName("f").bind("fBinding"))))
matches the decomposition decl with 'f' bound to "fBinding".
|
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2172,6 +2172,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
@@ -2389,6 +2400,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;
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===================================================================
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ 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;
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ 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);
Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ 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 "