Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -1926,6 +1926,19 @@ +Matcher<BinaryOperator>isAssignmentOperator +
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; })
+
+ + Matcher<CXXBoolLiteralExpr>equalsbool Value

 
@@ -2306,6 +2319,19 @@
 
 
 
+Matcher<CXXOperatorCallExpr>isAssignmentOperator
+
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; })
+
+ + Matcher<CXXRecordDecl>hasDefinition
Matches a class declaration that is defined.
 
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -4003,6 +4003,26 @@
   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()))
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -322,6 +322,7 @@
   REGISTER_MATCHER(isAnyPointer);
   REGISTER_MATCHER(isArray);
   REGISTER_MATCHER(isArrow);
+  REGISTER_MATCHER(isAssignmentOperator);
   REGISTER_MATCHER(isBaseInitializer);
   REGISTER_MATCHER(isBitField);
   REGISTER_MATCHER(isCatchAll);
Index: unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2139,5 +2139,20 @@
           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