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&lt;<a 
href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html";>BinaryOperator</a>&gt;</td><td
 class="name" onclick="toggle('hasOperands0')"><a 
name="hasOperands0Anchor">hasOperands</a></td><td>Matcher&lt;<a 
href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt;  
Matcher1, Matcher&lt;<a 
href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt;  
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&lt;<a 
href="https://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html";>BinaryOperator</a>&gt;</td><td
 class="name" onclick="toggle('hasRHS0')"><a 
name="hasRHS0Anchor">hasRHS</a></td><td>Matcher&lt;<a 
href="https://clang.llvm.org/doxygen/classclang_1_1Expr.html";>Expr</a>&gt; 
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

Reply via email to