Author: Nathan James Date: 2020-05-17T19:54:14+01:00 New Revision: 74bcb00e00f3ef971e4c584a124e99289f2ebf34
URL: https://github.com/llvm/llvm-project/commit/74bcb00e00f3ef971e4c584a124e99289f2ebf34 DIFF: https://github.com/llvm/llvm-project/commit/74bcb00e00f3ef971e4c584a124e99289f2ebf34.diff LOG: [ASTMatchers] Added BinaryOperator hasOperands matcher Summary: Adds a matcher called `hasOperands` for `BinaryOperator`'s when you need to match both sides but the order isn't important, usually on commutative operators. Reviewers: klimek, aaron.ballman, gribozavr2, alexfh Reviewed By: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D80054 Added: Modified: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h 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 f5106f0e0ba2..f57352389e4c 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -5033,6 +5033,18 @@ <h2 id="traversal-matchers">AST Traversal Matchers</h2> </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasOperands0')"><a name="hasOperands0Anchor">hasOperands</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher1, Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> Matcher2</td></tr> +<tr><td colspan="4" class="doc" id="hasOperands0"><pre>Matches if both matchers match with opposite sides of the binary operator. + +Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1), + integerLiteral(equals(2))) + 1 + 2 // Match + 2 + 1 // Match + 1 + 1 // No match + 2 + 2 // No match +</pre></td></tr> + + <tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>></td><td class="name" onclick="toggle('hasRHS0')"><a name="hasRHS0Anchor">hasRHS</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="hasRHS0"><pre>Matches the right hand side of binary operator expressions. diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index ce702bc44edd..460962d9e73b 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4869,6 +4869,23 @@ inline internal::Matcher<BinaryOperator> hasEitherOperand( return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); } +/// Matches if both matchers match with opposite sides of the binary operator. +/// +/// Example matcher = binaryOperator(hasOperands(integerLiteral(equals(1), +/// integerLiteral(equals(2))) +/// \code +/// 1 + 2 // Match +/// 2 + 1 // Match +/// 1 + 1 // No match +/// 2 + 2 // No match +/// \endcode +inline internal::Matcher<BinaryOperator> +hasOperands(const internal::Matcher<Expr> &Matcher1, + const internal::Matcher<Expr> &Matcher2) { + return anyOf(allOf(hasLHS(Matcher1), hasRHS(Matcher2)), + allOf(hasLHS(Matcher2), hasRHS(Matcher1))); +} + /// Matches if the operand of a unary operator matches. /// /// Example matches true (matcher = hasUnaryOperand( diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index e7659feaf1e9..0a7d09e55c88 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -294,6 +294,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(hasName); REGISTER_MATCHER(hasNullSelector); REGISTER_MATCHER(hasObjectExpression); + REGISTER_MATCHER(hasOperands); REGISTER_MATCHER(hasOperatorName); REGISTER_MATCHER(hasOverloadedOperatorName); REGISTER_MATCHER(hasParameter); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 2972fc91b908..0c9a3d9eb1ed 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1160,6 +1160,17 @@ TEST(MatchBinaryOperator, HasEitherOperand) { EXPECT_TRUE(notMatches("void x() { true || true; }", HasOperand)); } +TEST(MatchBinaryOperator, HasOperands) { + StatementMatcher HasOperands = binaryOperator( + hasOperands(integerLiteral(equals(1)), integerLiteral(equals(2)))); + EXPECT_TRUE(matches("void x() { 1 + 2; }", HasOperands)); + EXPECT_TRUE(matches("void x() { 2 + 1; }", HasOperands)); + EXPECT_TRUE(notMatches("void x() { 1 + 1; }", HasOperands)); + EXPECT_TRUE(notMatches("void x() { 2 + 2; }", HasOperands)); + EXPECT_TRUE(notMatches("void x() { 0 + 0; }", HasOperands)); + EXPECT_TRUE(notMatches("void x() { 0 + 1; }", HasOperands)); +} + TEST(Matcher, BinaryOperatorTypes) { // Integration test that verifies the AST provides all binary operators in // a way we expect. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits