Author: Chuanqi Xu Date: 2021-03-22T10:27:46+08:00 New Revision: 55486161fa0bc29519bf53f0e6302b14d8de5578
URL: https://github.com/llvm/llvm-project/commit/55486161fa0bc29519bf53f0e6302b14d8de5578 DIFF: https://github.com/llvm/llvm-project/commit/55486161fa0bc29519bf53f0e6302b14d8de5578.diff LOG: [ASTMatcher] Add AST Matcher support for C++20 coroutine keywords Summary: Try to enable the support for C++20 coroutine keywords for AST Matchers. Reviewers: sammccall, njames93, aaron.ballman Differential Revision: https://reviews.llvm.org/D96316 Added: Modified: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/ASTMatchersInternal.cpp clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Removed: ################################################################################ diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index 0d2570bcd58f..b8fb27b126fc 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -1337,6 +1337,16 @@ <h2 id="decl-matchers">Node Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('coawaitExpr0')"><a name="coawaitExpr0Anchor">coawaitExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CoawaitExpr.html">CoawaitExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="coawaitExpr0"><pre>Matches co_await expressions. + +Given + co_await 1; +coawaitExpr() + matches 'co_await 1' +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('compoundLiteralExpr0')"><a name="compoundLiteralExpr0Anchor">compoundLiteralExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CompoundLiteralExpr.html">CompoundLiteralExpr</a>>...</td></tr> <tr><td colspan="4" class="doc" id="compoundLiteralExpr0"><pre>Matches compound (i.e. non-scalar) literals @@ -1383,6 +1393,26 @@ <h2 id="decl-matchers">Node Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('coreturnStmt0')"><a name="coreturnStmt0Anchor">coreturnStmt</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CoreturnStmt.html">CoreturnStmt</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="coreturnStmt0"><pre>Matches co_return statements. + +Given + while (true) { co_return; } +coreturnStmt() + matches 'co_return' +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('coyieldExpr0')"><a name="coyieldExpr0Anchor">coyieldExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CoyieldExpr.html">CoyieldExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="coyieldExpr0"><pre>Matches co_yield expressions. + +Given + co_yield 1; +coyieldExpr() + matches 'co_yield 1' +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('cudaKernelCallExpr0')"><a name="cudaKernelCallExpr0Anchor">cudaKernelCallExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CUDAKernelCallExpr.html">CUDAKernelCallExpr</a>>...</td></tr> <tr><td colspan="4" class="doc" id="cudaKernelCallExpr0"><pre>Matches CUDA kernel call expression. @@ -1698,6 +1728,11 @@ <h2 id="decl-matchers">Node Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('dependentCoawaitExpr0')"><a name="dependentCoawaitExpr0Anchor">dependentCoawaitExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DependentCoawaitExpr.html">DependentCoawaitExpr</a>>...</td></tr> +<tr><td colspan="4" class="doc" id="dependentCoawaitExpr0"><pre>Matches co_await expressions where the type of the promise is dependent +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Stmt.html">Stmt</a>></td><td class="name" onclick="toggle('designatedInitExpr0')"><a name="designatedInitExpr0Anchor">designatedInitExpr</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1DesignatedInitExpr.html">DesignatedInitExpr</a>>...</td></tr> <tr><td colspan="4" class="doc" id="designatedInitExpr0"><pre>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 index 64e8cecf4822..fd0e9d6d7c1f 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -2162,6 +2162,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; +/// Matches co_return statements. +/// +/// Given +/// \code +/// while (true) { co_return; } +/// \endcode +/// coreturnStmt() +/// matches 'co_return' +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoreturnStmt> + coreturnStmt; + /// Matches return statements. /// /// Given @@ -2379,6 +2390,30 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> compoundLiteralExpr; +/// Matches co_await expressions. +/// +/// Given +/// \code +/// co_await 1; +/// \endcode +/// coawaitExpr() +/// matches 'co_await 1' +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoawaitExpr> + coawaitExpr; +/// Matches co_await expressions where the type of the promise is dependent +extern const internal::VariadicDynCastAllOfMatcher<Stmt, DependentCoawaitExpr> + dependentCoawaitExpr; +/// Matches co_yield expressions. +/// +/// Given +/// \code +/// co_yield 1; +/// \endcode +/// coyieldExpr() +/// matches 'co_yield 1' +extern const internal::VariadicDynCastAllOfMatcher<Stmt, CoyieldExpr> + coyieldExpr; + /// Matches nullptr literal. extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index b20a60425661..c2001070de55 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -883,6 +883,7 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; +const internal::VariadicDynCastAllOfMatcher<Stmt, CoreturnStmt> coreturnStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; @@ -915,6 +916,12 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, ChooseExpr> chooseExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CoawaitExpr> + coawaitExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, DependentCoawaitExpr> + dependentCoawaitExpr; +const internal::VariadicDynCastAllOfMatcher<Stmt, CoyieldExpr> + coyieldExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; const internal::VariadicDynCastAllOfMatcher<Stmt, GenericSelectionExpr> genericSelectionExpr; diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index bfc46b7742d6..8e595deac2cd 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -166,11 +166,14 @@ RegistryMaps::RegistryMaps() { 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 @@ RegistryMaps::RegistryMaps() { 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 index 9909cec2065c..bf4b0912c661 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -510,6 +510,83 @@ void foo() varDecl(hasName("lPtrDecay")))))))); } +TEST(Matcher, MatchesCoroutine) { + FileContentMappings M; + M.push_back(std::make_pair("/coro_header", R"cpp( +namespace std { +namespace experimental { + +template <class... Args> +struct void_t_imp { + using type = void; +}; +template <class... Args> +using void_t = typename void_t_imp<Args...>::type; + +template <class T, class = void> +struct traits_sfinae_base {}; + +template <class T> +struct traits_sfinae_base<T, void_t<typename T::promise_type>> { + using promise_type = typename T::promise_type; +}; + +template <class Ret, class... Args> +struct coroutine_traits : public traits_sfinae_base<Ret> {}; +}} // namespace std::experimental +struct awaitable { + bool await_ready() noexcept; + template <typename F> + 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 <typename... T> +struct std::experimental::coroutine_traits<void, T...> { using promise_type = promise; }; +namespace std { +namespace experimental { +template <class PromiseType = void> +struct coroutine_handle { + static coroutine_handle from_address(void *) noexcept; +}; +}} // namespace std::experimental +)cpp")); + StringRef CoReturnCode = R"cpp( +#include <coro_header> +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 <coro_header> +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 <coro_header> +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 " _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits