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 @@ +
Matches co_await expressions. + +Given + co_await 1; +coawaitExpr() + matches 'co_await 1' +
Matches compound (i.e. non-scalar) literals @@ -1383,6 +1393,26 @@
Matches co_return statements. + +Given + while (true) { co_return; } +coreturnStmt() + matches 'co_return' +
Matches co_yield expressions. + +Given + co_yield 1; +coyieldExpr() + matches 'co_yield 1' +
Matches CUDA kernel call expression. @@ -1698,6 +1728,11 @@
Matches co_await expressions where the type of the promise is dependent +
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::VariadicDynCastAllOfMatchercontinueStmt; +/// 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 "