diff --git a/clang/docs/LibASTMatchersReference.html b/clang/docs/LibASTMatchersReference.html --- a/clang/docs/LibASTMatchersReference.html +++ b/clang/docs/LibASTMatchersReference.html @@ -2599,6 +2599,18 @@ +Matcher<CXXOperatorCallExpr>hasAnyOverloadedOperatorNameStringRef, ..., StringRef +
Matches overloaded operator names.
+
+Matches overloaded operator names specified in strings without the
+"operator" prefix: e.g. "<<".
+
+  hasAnyOverloadesOperatorName("+", "-")
+Is equivalent to
+  anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
+
+ + Matcher<CXXOperatorCallExpr>hasOverloadedOperatorNameStringRef Name
Matches overloaded operator names.
 
@@ -3178,6 +3190,18 @@
 

 
 
+Matcher<FunctionDecl>hasAnyOverloadedOperatorNameStringRef, ..., StringRef
+
Matches overloaded operator names.
+
+Matches overloaded operator names specified in strings without the
+"operator" prefix: e.g. "<<".
+
+  hasAnyOverloadesOperatorName("+", "-")
+Is equivalent to
+  anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
+
+ + Matcher<FunctionDecl>hasDynamicExceptionSpec
Matches functions that have a dynamic exception specification.
 
diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h
--- a/clang/include/clang/ASTMatchers/ASTMatchers.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -2749,14 +2749,30 @@
 ///
 /// Usable as: Matcher, Matcher
 inline internal::PolymorphicMatcherWithParam1<
-    internal::HasOverloadedOperatorNameMatcher, StringRef,
+    internal::HasOverloadedOperatorNameMatcher, std::vector,
     AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>
 hasOverloadedOperatorName(StringRef Name) {
   return internal::PolymorphicMatcherWithParam1<
-      internal::HasOverloadedOperatorNameMatcher, StringRef,
-      AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name);
+      internal::HasOverloadedOperatorNameMatcher, std::vector,
+      AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(
+      {std::string(Name)});
 }
 
+/// Matches overloaded operator names.
+///
+/// Matches overloaded operator names specified in strings without the
+/// "operator" prefix: e.g. "<<".
+///
+///   hasAnyOverloadesOperatorName("+", "-")
+/// Is equivalent to
+///   anyOf(hasOverloadedOperatorName("+"), hasOverloadedOperatorName("-"))
+extern const internal::VariadicFunction<
+    internal::PolymorphicMatcherWithParam1<
+        internal::HasOverloadedOperatorNameMatcher, std::vector,
+        AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>,
+    StringRef, internal::hasAnyOverloadedOperatorNameFunc>
+    hasAnyOverloadedOperatorName;
+
 /// Matches C++ classes that are directly or indirectly derived from a class
 /// matching \c Base, or Objective-C classes that directly or indirectly
 /// subclass a class matching \c Base.
diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
--- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -670,12 +670,12 @@
   static_assert(std::is_same::value ||
                 std::is_base_of::value,
                 "unsupported class for matcher");
-  static_assert(std::is_same::value,
-                "argument type must be StringRef");
+  static_assert(std::is_same>::value,
+                "argument type must be std::vector");
 
 public:
-  explicit HasOverloadedOperatorNameMatcher(const StringRef Name)
-      : SingleNodeMatcherInterface(), Name(Name) {}
+  explicit HasOverloadedOperatorNameMatcher(std::vector Names)
+      : SingleNodeMatcherInterface(), Names(std::move(Names)) {}
 
   bool matchesNode(const T &Node) const override {
     return matchesSpecialized(Node);
@@ -687,17 +687,18 @@
   /// so this function returns true if the call is to an operator of the given
   /// name.
   bool matchesSpecialized(const CXXOperatorCallExpr &Node) const {
-    return getOperatorSpelling(Node.getOperator()) == Name;
+    return llvm::is_contained(Names, getOperatorSpelling(Node.getOperator()));
   }
 
   /// Returns true only if CXXMethodDecl represents an overloaded
   /// operator and has the given operator name.
   bool matchesSpecialized(const FunctionDecl &Node) const {
     return Node.isOverloadedOperator() &&
-           getOperatorSpelling(Node.getOverloadedOperator()) == Name;
+           llvm::is_contained(
+               Names, getOperatorSpelling(Node.getOverloadedOperator()));
   }
 
-  std::string Name;
+  const std::vector Names;
 };
 
 /// Matches named declarations with a specific name.
@@ -1899,6 +1900,13 @@
 
 HasOpNameMatcher hasAnyOperatorNameFunc(ArrayRef NameRefs);
 
+using HasOverloadOpNameMatcher = PolymorphicMatcherWithParam1<
+    HasOverloadedOperatorNameMatcher, std::vector,
+    void(TypeList)>;
+
+HasOverloadOpNameMatcher
+hasAnyOverloadedOperatorNameFunc(ArrayRef NameRefs);
+
 } // namespace internal
 
 } // namespace ast_matchers
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -378,6 +378,11 @@
   return HasOpNameMatcher(vectorFromRefs(NameRefs));
 }
 
+HasOverloadOpNameMatcher
+hasAnyOverloadedOperatorNameFunc(ArrayRef NameRefs) {
+  return HasOverloadOpNameMatcher(vectorFromRefs(NameRefs));
+}
+
 HasNameMatcher::HasNameMatcher(std::vector N)
     : UseUnqualifiedMatch(llvm::all_of(
           N, [](StringRef Name) { return Name.find("::") == Name.npos; })),
@@ -861,6 +866,9 @@
 const internal::VariadicFunction
     hasAnyOperatorName = {};
+const internal::VariadicFunction
+    hasAnyOverloadedOperatorName = {};
 const internal::VariadicFunction, StringRef,
                                  internal::hasAnySelectorFunc>
     hasAnySelector = {};
diff --git a/clang/lib/ASTMatchers/Dynamic/Registry.cpp b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
--- a/clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -244,6 +244,7 @@
   REGISTER_MATCHER(hasAnyDeclaration);
   REGISTER_MATCHER(hasAnyName);
   REGISTER_MATCHER(hasAnyOperatorName);
+  REGISTER_MATCHER(hasAnyOverloadedOperatorName);
   REGISTER_MATCHER(hasAnyParameter);
   REGISTER_MATCHER(hasAnyPlacementArg);
   REGISTER_MATCHER(hasAnySelector);
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -898,6 +898,12 @@
   DeclarationMatcher AnyOpStar = functionDecl(hasOverloadedOperatorName("*"));
   EXPECT_TRUE(matches("class Y; int operator*(Y &);", AnyOpStar));
   EXPECT_TRUE(matches("class Y { int operator*(); };", AnyOpStar));
+  DeclarationMatcher AnyAndOp =
+      functionDecl(hasAnyOverloadedOperatorName("&", "&&"));
+  EXPECT_TRUE(matches("class Y; Y operator&(Y &, Y &);", AnyAndOp));
+  EXPECT_TRUE(matches("class Y; Y operator&&(Y &, Y &);", AnyAndOp));
+  EXPECT_TRUE(matches("class Y { Y operator&(Y &); };", AnyAndOp));
+  EXPECT_TRUE(matches("class Y { Y operator&&(Y &); };", AnyAndOp));
 }