Author: Nathan James Date: 2020-03-09T00:05:10Z New Revision: fc3c80c38643aff6c4744433ab485c7550ee77b9
URL: https://github.com/llvm/llvm-project/commit/fc3c80c38643aff6c4744433ab485c7550ee77b9 DIFF: https://github.com/llvm/llvm-project/commit/fc3c80c38643aff6c4744433ab485c7550ee77b9.diff LOG: [ASTMatchers] adds isComparisonOperator to BinaryOperator and CXXOperatorCallExpr Reviewers: aaron.ballman, gribozavr2 Reviewed By: aaron.ballman Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D75800 Added: Modified: clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp clang/docs/LibASTMatchersReference.html clang/include/clang/AST/ExprCXX.h clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp Removed: ################################################################################ diff --git a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp index 90fcf38f83b7..99214ccf2e79 100644 --- a/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp @@ -567,7 +567,7 @@ matchRelationalIntegerConstantExpr(StringRef Id) { std::string OverloadId = (Id + "-overload").str(); const auto RelationalExpr = ignoringParenImpCasts(binaryOperator( - isComparisonOperator(), expr().bind(Id), + matchers::isComparisonOperator(), expr().bind(Id), anyOf(allOf(hasLHS(matchSymbolicExpr(Id)), hasRHS(matchIntegerConstantExpr(Id))), allOf(hasLHS(matchIntegerConstantExpr(Id)), @@ -943,7 +943,7 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { const auto SymRight = matchSymbolicExpr("rhs"); // Match expressions like: x <op> 0xFF == 0xF00. - Finder->addMatcher(binaryOperator(isComparisonOperator(), + Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(), hasEitherOperand(BinOpCstLeft), hasEitherOperand(CstRight)) .bind("binop-const-compare-to-const"), @@ -951,14 +951,14 @@ void RedundantExpressionCheck::registerMatchers(MatchFinder *Finder) { // Match expressions like: x <op> 0xFF == x. Finder->addMatcher( - binaryOperator(isComparisonOperator(), + binaryOperator(matchers::isComparisonOperator(), anyOf(allOf(hasLHS(BinOpCstLeft), hasRHS(SymRight)), allOf(hasLHS(SymRight), hasRHS(BinOpCstLeft)))) .bind("binop-const-compare-to-sym"), this); // Match expressions like: x <op> 10 == x <op> 12. - Finder->addMatcher(binaryOperator(isComparisonOperator(), + Finder->addMatcher(binaryOperator(matchers::isComparisonOperator(), hasLHS(BinOpCstLeft), hasRHS(BinOpCstRight), // Already reported as redundant. unless(operandsAreEquivalent())) diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html index dca7aa5c2cf7..f0faed7f0f8f 100644 --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2157,7 +2157,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator())) struct S { S& operator=(const S&); }; - void x() { S s1, s2; s1 = s2; }) + void x() { S s1, s2; s1 = s2; } +</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('isComparisonOperator0')"><a name="isComparisonOperator0Anchor">isComparisonOperator</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isComparisonOperator0"><pre>Matches comparison operators. + +Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator())) + if (a == b) + a += b; + +Example 2: matches s1 < s2 + (matcher = cxxOperatorCallExpr(isComparisonOperator())) + struct S { bool operator<(const S& other); }; + void x(S s1, S s2) { bool b1 = s1 < s2; } </pre></td></tr> @@ -2616,7 +2630,21 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2> Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator())) struct S { S& operator=(const S&); }; - void x() { S s1, s2; s1 = s2; }) + void x() { S s1, s2; s1 = s2; } +</pre></td></tr> + + +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>></td><td class="name" onclick="toggle('isComparisonOperator1')"><a name="isComparisonOperator1Anchor">isComparisonOperator</a></td><td></td></tr> +<tr><td colspan="4" class="doc" id="isComparisonOperator1"><pre>Matches comparison operators. + +Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator())) + if (a == b) + a += b; + +Example 2: matches s1 < s2 + (matcher = cxxOperatorCallExpr(isComparisonOperator())) + struct S { bool operator<(const S& other); }; + void x(S s1, S s2) { bool b1 = s1 < s2; } </pre></td></tr> diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index cea360d12e91..2bd68eec175a 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -118,6 +118,22 @@ class CXXOperatorCallExpr final : public CallExpr { } bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } + static bool isComparisonOp(OverloadedOperatorKind Opc) { + switch (Opc) { + case OO_EqualEqual: + case OO_ExclaimEqual: + case OO_Greater: + case OO_GreaterEqual: + case OO_Less: + case OO_LessEqual: + case OO_Spaceship: + return true; + default: + return false; + } + } + bool isComparisonOp() const { return isComparisonOp(getOperator()); } + /// Is this written as an infix binary operator? bool isInfixBinaryOp() const; diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index da7e23052b28..31138e47750c 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4783,7 +4783,7 @@ extern const internal::VariadicFunction< /// (matcher = cxxOperatorCallExpr(isAssignmentOperator())) /// \code /// struct S { S& operator=(const S&); }; -/// void x() { S s1, s2; s1 = s2; }) +/// void x() { S s1, s2; s1 = s2; } /// \endcode AST_POLYMORPHIC_MATCHER(isAssignmentOperator, AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, @@ -4791,6 +4791,26 @@ AST_POLYMORPHIC_MATCHER(isAssignmentOperator, return Node.isAssignmentOp(); } +/// Matches comparison operators. +/// +/// Example 1: matches a == b (matcher = binaryOperator(isComparisonOperator())) +/// \code +/// if (a == b) +/// a += b; +/// \endcode +/// +/// Example 2: matches s1 < s2 +/// (matcher = cxxOperatorCallExpr(isComparisonOperator())) +/// \code +/// struct S { bool operator<(const S& other); }; +/// void x(S s1, S s2) { bool b1 = s1 < s2; } +/// \endcode +AST_POLYMORPHIC_MATCHER(isComparisonOperator, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr)) { + return Node.isComparisonOp(); +} + /// Matches the left hand side of binary operator expressions. /// /// Example matches a (matcher = binaryOperator(hasLHS())) diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp index 5452b408a817..fd2b6b253c53 100644 --- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -358,6 +358,7 @@ RegistryMaps::RegistryMaps() { REGISTER_MATCHER(isClass); REGISTER_MATCHER(isClassMessage); REGISTER_MATCHER(isClassMethod); + REGISTER_MATCHER(isComparisonOperator); REGISTER_MATCHER(isConst); REGISTER_MATCHER(isConstQualified); REGISTER_MATCHER(isConstexpr); diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp index c3c770a7dffd..2816e216e8c4 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -2689,6 +2689,20 @@ TEST(IsAssignmentOperator, Basic) { notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator)); } +TEST(IsComparisonOperator, Basic) { + StatementMatcher BinCompOperator = binaryOperator(isComparisonOperator()); + StatementMatcher CXXCompOperator = + cxxOperatorCallExpr(isComparisonOperator()); + + EXPECT_TRUE(matches("void x() { int a; a == 1; }", BinCompOperator)); + EXPECT_TRUE(matches("void x() { int a; a > 2; }", BinCompOperator)); + EXPECT_TRUE(matches("struct S { bool operator==(const S&); };" + "void x() { S s1, s2; bool b1 = s1 == s2; }", + CXXCompOperator)); + EXPECT_TRUE( + notMatches("void x() { int a; if(a = 0) return; }", BinCompOperator)); +} + TEST(HasInit, Basic) { EXPECT_TRUE( matches("int x{0};", _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits