forked from OSchip/llvm-project
[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
This commit is contained in:
parent
073dbaae39
commit
fc3c80c386
|
@ -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()))
|
||||
|
|
|
@ -2157,7 +2157,21 @@ Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
|
|||
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 @@ Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
|
|||
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>
|
||||
|
||||
|
||||
|
|
|
@ -118,6 +118,22 @@ public:
|
|||
}
|
||||
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;
|
||||
|
||||
|
|
|
@ -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()))
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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};",
|
||||
|
|
Loading…
Reference in New Issue