[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher

2021-01-16 Thread Stephen Kelly via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe810e95e4bb9: [ASTMatchers] Add binaryOperation matcher 
(authored by stephenkelly).

Changed prior to commit:
  https://reviews.llvm.org/D94129?vs=316749=317172#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94129/new/

https://reviews.llvm.org/D94129

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Marshallers.h
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -470,6 +470,10 @@
 return;
   }
 
+  if (GetParam().hasDelayedTemplateParsing()) {
+return;
+  }
+
   StringRef Code = R"cpp(
 void F() {
   if (true) {}
@@ -556,6 +560,15 @@
 if (s1 != s2)
 return;
 }
+
+template
+void templ()
+{
+T s1;
+T s2;
+if (s1 != s2)
+return;
+}
 )cpp";
 
   EXPECT_TRUE(matches(
@@ -669,6 +682,38 @@
  .with(hasAnyOperatorName("==", "!="),
forFunction(functionDecl(hasName("opFree")));
 
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("binop"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("opMem"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("opFree"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("templ"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
   Code = R"cpp(
 struct HasOpBangMem
 {
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -143,6 +143,7 @@
   REGISTER_MATCHER(autoreleasePoolStmt)
   REGISTER_MATCHER(binaryConditionalOperator);
   REGISTER_MATCHER(binaryOperator);
+  REGISTER_MATCHER(binaryOperation);
   REGISTER_MATCHER(blockDecl);
   REGISTER_MATCHER(blockExpr);
   REGISTER_MATCHER(blockPointerType);
Index: clang/lib/ASTMatchers/Dynamic/Marshallers.h
===
--- clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -925,6 +925,50 @@
   const StringRef MatcherName;
 };
 
+template 
+class MapAnyOfMatcherDescriptor : public MatcherDescriptor {
+  std::vector Funcs;
+
+public:
+  MapAnyOfMatcherDescriptor(StringRef MatcherName)
+  : Funcs{DynCastAllOfMatcherDescriptor(
+ast_matchers::internal::VariadicDynCastAllOfMatcher{},
+MatcherName)...} {}
+
+  VariantMatcher create(SourceRange NameRange, ArrayRef Args,
+Diagnostics *Error) const override {
+std::vector InnerArgs;
+
+for (auto const  : Funcs) {
+  InnerArgs.push_back(F.create(NameRange, Args, Error));
+  if (!Error->errors().empty())
+return {};
+}
+return VariantMatcher::SingleMatcher(
+ast_matchers::internal::BindableMatcher(
+VariantMatcher::VariadicOperatorMatcher(
+ast_matchers::internal::DynTypedMatcher::VO_AnyOf,
+std::move(InnerArgs))
+.getTypedMatcher()));
+  }
+
+  bool isVariadic() const override { return true; }
+  unsigned getNumArgs() const override { return 0; }
+
+  void 

[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher

2021-01-15 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman accepted this revision.
aaron.ballman added a comment.
This revision is now accepted and ready to land.

LGTM aside from some minor NFC improvements.




Comment at: clang/lib/ASTMatchers/Dynamic/Marshallers.h:957
+
+  void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo,
+   std::vector ) const override {





Comment at: clang/lib/ASTMatchers/Dynamic/Marshallers.h:964-968
+for (auto const  : Funcs) {
+  if (F.isConvertibleTo(Kind, Specificity, LeastDerivedKind))
+return true;
+}
+return false;




Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94129/new/

https://reviews.llvm.org/D94129

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher

2021-01-14 Thread Stephen Kelly via Phabricator via cfe-commits
steveire updated this revision to Diff 316749.
steveire added a comment.

Update


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94129/new/

https://reviews.llvm.org/D94129

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/lib/ASTMatchers/Dynamic/Marshallers.h
  clang/lib/ASTMatchers/Dynamic/Registry.cpp
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -470,6 +470,10 @@
 return;
   }
 
+  if (GetParam().hasDelayedTemplateParsing()) {
+return;
+  }
+
   StringRef Code = R"cpp(
 void F() {
   if (true) {}
@@ -541,6 +545,15 @@
 if (s1 != s2)
 return;
 }
+
+template
+void templ()
+{
+T s1;
+T s2;
+if (s1 != s2)
+return;
+}
 )cpp";
 
   EXPECT_TRUE(matches(
@@ -617,6 +630,30 @@
  .with(hasAnyOperatorName("==", "!="),
forFunction(functionDecl(hasName("opCall")));
 
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("binop"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("opCall"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("templ"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
   Code = R"cpp(
 struct HasOpBang
 {
Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp
===
--- clang/lib/ASTMatchers/Dynamic/Registry.cpp
+++ clang/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -143,6 +143,7 @@
   REGISTER_MATCHER(autoreleasePoolStmt)
   REGISTER_MATCHER(binaryConditionalOperator);
   REGISTER_MATCHER(binaryOperator);
+  REGISTER_MATCHER(binaryOperation);
   REGISTER_MATCHER(blockDecl);
   REGISTER_MATCHER(blockExpr);
   REGISTER_MATCHER(blockPointerType);
Index: clang/lib/ASTMatchers/Dynamic/Marshallers.h
===
--- clang/lib/ASTMatchers/Dynamic/Marshallers.h
+++ clang/lib/ASTMatchers/Dynamic/Marshallers.h
@@ -925,6 +925,50 @@
   const StringRef MatcherName;
 };
 
+template 
+class MapAnyOfMatcherDescriptor : public MatcherDescriptor {
+  std::vector Funcs;
+
+public:
+  MapAnyOfMatcherDescriptor(StringRef MatcherName)
+  : Funcs{DynCastAllOfMatcherDescriptor(
+ast_matchers::internal::VariadicDynCastAllOfMatcher{},
+MatcherName)...} {}
+
+  VariantMatcher create(SourceRange NameRange, ArrayRef Args,
+Diagnostics *Error) const override {
+std::vector InnerArgs;
+
+for (auto const  : Funcs) {
+  InnerArgs.push_back(F.create(NameRange, Args, Error));
+}
+return VariantMatcher::SingleMatcher(
+ast_matchers::internal::BindableMatcher(
+VariantMatcher::VariadicOperatorMatcher(
+ast_matchers::internal::DynTypedMatcher::VO_AnyOf,
+std::move(InnerArgs))
+.getTypedMatcher()));
+  }
+
+  bool isVariadic() const override { return true; }
+  unsigned getNumArgs() const override { return 0; }
+
+  void getArgKinds(ASTNodeKind ThisKind, unsigned ArgNo,
+   std::vector ) const override {
+Kinds.push_back(ThisKind);
+  }
+
+  bool isConvertibleTo(ASTNodeKind Kind, unsigned *Specificity,
+   ASTNodeKind *LeastDerivedKind) const override {
+for (auto const  : Funcs) {
+  if (F.isConvertibleTo(Kind, Specificity, LeastDerivedKind))
+return true;
+}
+return false;
+  }
+};
+
 /// Helper functions to select the appropriate marshaller functions.
 /// They detect the number of arguments, arguments types and return type.
 
@@ -1029,6 +1073,14 @@
   MinCount, MaxCount, Func.Op, MatcherName);
 }
 
+template 
+std::unique_ptr 

[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher

2021-01-11 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added inline comments.



Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:2739
 
+/// Matches nodes which can be used with binary operators
+///





Comment at: clang/include/clang/ASTMatchers/ASTMatchers.h:2785
+internal::BindableMatcher
+binaryOperation(InnerMatcherType &&... Matchers) {
+  return mapAnyOf(binaryOperator, cxxOperatorCallExpr).with(Matchers...);

Missing changes to Registry.cpp to expose this to clang-query?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D94129/new/

https://reviews.llvm.org/D94129

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D94129: [ASTMatchers] Add binaryOperation matcher

2021-01-05 Thread Stephen Kelly via Phabricator via cfe-commits
steveire created this revision.
steveire added a reviewer: aaron.ballman.
steveire requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This is a simple utility which allows matching on binaryOperator and
cxxOperatorCallExpr. It can also be extended to support
cxxRewrittenBinaryOperator.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D94129

Files:
  clang/docs/LibASTMatchersReference.html
  clang/docs/tools/dump_ast_matchers.py
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -478,6 +478,10 @@
 return;
   }
 
+  if (GetParam().hasDelayedTemplateParsing()) {
+return;
+  }
+
   StringRef Code = R"cpp(
 void F() {
   if (true) {}
@@ -549,6 +553,15 @@
 if (s1 != s2)
 return;
 }
+
+template
+void templ()
+{
+T s1;
+T s2;
+if (s1 != s2)
+return;
+}
 )cpp";
 
   EXPECT_TRUE(matches(
@@ -625,6 +638,30 @@
  .with(hasAnyOperatorName("==", "!="),
forFunction(functionDecl(hasName("opCall")));
 
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("binop"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("opCall"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
+  EXPECT_TRUE(matches(
+  Code, traverse(TK_IgnoreUnlessSpelledInSource,
+ binaryOperation(
+ hasOperatorName("!="),
+ forFunction(functionDecl(hasName("templ"))),
+ hasLHS(declRefExpr(to(varDecl(hasName("s1"),
+ hasRHS(declRefExpr(to(varDecl(hasName("s2");
+
   Code = R"cpp(
 struct HasOpBang
 {
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -1973,6 +1973,8 @@
 ///   ostream  int b = 1, c = 1;
 ///   o << b << c;
 /// \endcode
+/// See also the binaryOperation() matcher for more-general matching of binary
+/// uses of this AST node.
 extern const internal::VariadicDynCastAllOfMatcher
 cxxOperatorCallExpr;
 
@@ -2395,6 +2397,7 @@
 /// \code
 ///   !(a || b)
 /// \endcode
+/// See also the binaryOperation() matcher for more-general matching.
 extern const internal::VariadicDynCastAllOfMatcher
 binaryOperator;
 
@@ -2733,6 +2736,56 @@
   NodeMatcher...);
 }
 
+/// Matches nodes which can be used with binary operators
+///
+/// The code
+/// \code
+///   var1 != var2;
+/// \endcode
+/// might be represented in the clang AST as a binaryOperator or a
+/// cxxOperatorCallExpr, depending on
+///
+/// * whether the types of var1 and var2 are fundamental (binaryOperator) or at
+///   least one is a class type (cxxOperatorCallExpr)
+/// * whether the code appears in a template declaration, if at least one of the
+///   vars is a dependent-type (binaryOperator)
+///
+/// This matcher elides details in places where the matchers for the nodes are
+/// compatible.
+///
+/// Given
+/// \code
+///   binaryOperation(
+/// hasOperatorName("!="),
+/// hasLHS(expr().bind("lhs")),
+/// hasRHS(expr().bind("rhs"))
+///   )
+/// \endcode
+/// matches each use of "!=" in:
+/// \code
+///   struct S{
+///   bool operator!=(const S&) const;
+///   };
+///
+///   void foo()
+///   {
+///  1 != 2;
+///  S() != S();
+///   }
+///
+///   template
+///   void templ()
+///   {
+///  1 != 2;
+///  T() != S();
+///   }
+/// \endcode
+template 
+internal::BindableMatcher
+binaryOperation(InnerMatcherType &&... Matchers) {
+  return mapAnyOf(binaryOperator, cxxOperatorCallExpr).with(Matchers...);
+}
+
 /// Matches unary expressions that have a specific type of argument.
 ///
 /// Given
Index: clang/docs/tools/dump_ast_matchers.py
===
--- clang/docs/tools/dump_ast_matchers.py
+++ clang/docs/tools/dump_ast_matchers.py
@@ -126,6 +126,9 @@
 args = "nodeMatcherFunction..."
 docs_result_type =