Skip to content

Commit

Permalink
[ASTMatchers] Add isAssignmentOperator matcher
Browse files Browse the repository at this point in the history
Adding a matcher for BinaryOperator and cxxOperatorCallExpr to be able to
decide whether it is any kind of assignment operator or not. This would be
useful since allows us to easily detect assignments via matchers for static
analysis (Tidy, SA) purposes.

Differential Revision: https://reviews.llvm.org/D44893

llvm-svn: 328618
  • Loading branch information
szepet committed Mar 27, 2018
1 parent 06cf6a6 commit fff11db
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 0 deletions.
26 changes: 26 additions & 0 deletions clang/docs/LibASTMatchersReference.html
Expand Up @@ -1926,6 +1926,19 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1BinaryOperator.html">BinaryOperator</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator0')"><a name="isAssignmentOperator0Anchor">isAssignmentOperator</a></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator0"><pre>Matches all kinds of assignment operators.

Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
if (a == b)
a += b;

Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
struct S { S& operator=(const S&); };
void x() { S s1, s2; s1 = s2; })
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXBoolLiteralExpr.html">CXXBoolLiteralExpr</a>&gt;</td><td class="name" onclick="toggle('equals5')"><a name="equals5Anchor">equals</a></td><td>bool Value</td></tr>
<tr><td colspan="4" class="doc" id="equals5"><pre></pre></td></tr>

Expand Down Expand Up @@ -2306,6 +2319,19 @@ <h2 id="narrowing-matchers">Narrowing Matchers</h2>
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXOperatorCallExpr.html">CXXOperatorCallExpr</a>&gt;</td><td class="name" onclick="toggle('isAssignmentOperator1')"><a name="isAssignmentOperator1Anchor">isAssignmentOperator</a></td></tr>
<tr><td colspan="4" class="doc" id="isAssignmentOperator1"><pre>Matches all kinds of assignment operators.

Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
if (a == b)
a += b;

Example 2: matches s1 = s2 (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
struct S { S& operator=(const S&); };
void x() { S s1, s2; s1 = s2; })
</pre></td></tr>


<tr><td>Matcher&lt;<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXRecordDecl.html">CXXRecordDecl</a>&gt;</td><td class="name" onclick="toggle('hasDefinition0')"><a name="hasDefinition0Anchor">hasDefinition</a></td><td></td></tr>
<tr><td colspan="4" class="doc" id="hasDefinition0"><pre>Matches a class declaration that is defined.

Expand Down
20 changes: 20 additions & 0 deletions clang/include/clang/ASTMatchers/ASTMatchers.h
Expand Up @@ -4003,6 +4003,26 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName,
return Name == Node.getOpcodeStr(Node.getOpcode());
}

/// \brief Matches on all kinds of assignment operators.
///
/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator()))
/// \code
/// if (a == b)
/// a += b;
/// \endcode
///
/// Example 2: matches s1 = s2
/// (matcher = cxxOperatorCallExpr(isAssignmentOperator()))
/// \code
/// struct S { S& operator=(const S&); };
/// void x() { S s1, s2; s1 = s2; })
/// \endcode
AST_POLYMORPHIC_MATCHER(isAssignmentOperator,
AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator,
CXXOperatorCallExpr)) {
return Node.isAssignmentOp();
}

/// \brief Matches the left hand side of binary operator expressions.
///
/// Example matches a (matcher = binaryOperator(hasLHS()))
Expand Down
1 change: 1 addition & 0 deletions clang/lib/ASTMatchers/Dynamic/Registry.cpp
Expand Up @@ -322,6 +322,7 @@ RegistryMaps::RegistryMaps() {
REGISTER_MATCHER(isAnyPointer);
REGISTER_MATCHER(isArray);
REGISTER_MATCHER(isArrow);
REGISTER_MATCHER(isAssignmentOperator);
REGISTER_MATCHER(isBaseInitializer);
REGISTER_MATCHER(isBitField);
REGISTER_MATCHER(isCatchAll);
Expand Down
15 changes: 15 additions & 0 deletions clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Expand Up @@ -2139,5 +2139,20 @@ TEST(HasTrailingReturn, MatchesLambdaTrailingReturn) {
functionDecl(hasTrailingReturn())));
}

TEST(IsAssignmentOperator, Basic) {
StatementMatcher BinAsgmtOperator = binaryOperator(isAssignmentOperator());
StatementMatcher CXXAsgmtOperator =
cxxOperatorCallExpr(isAssignmentOperator());

EXPECT_TRUE(matches("void x() { int a; a += 1; }", BinAsgmtOperator));
EXPECT_TRUE(matches("void x() { int a; a = 2; }", BinAsgmtOperator));
EXPECT_TRUE(matches("void x() { int a; a &= 3; }", BinAsgmtOperator));
EXPECT_TRUE(matches("struct S { S& operator=(const S&); };"
"void x() { S s1, s2; s1 = s2; }",
CXXAsgmtOperator));
EXPECT_TRUE(
notMatches("void x() { int a; if(a == 0) return; }", BinAsgmtOperator));
}

} // namespace ast_matchers
} // namespace clang

0 comments on commit fff11db

Please sign in to comment.