[PATCH] D80685: [ASTMatchers] Add traversal-kind support to `DynTypedMatcher`

2020-05-28 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
ymandel marked an inline comment as done.
Closed by commit rG04a96aa3e430: [ASTMatchers] Add traversal-kind support to 
`DynTypedMatcher` (authored by ymandel).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80685

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
  clang/unittests/ASTMatchers/CMakeLists.txt

Index: clang/unittests/ASTMatchers/CMakeLists.txt
===
--- clang/unittests/ASTMatchers/CMakeLists.txt
+++ clang/unittests/ASTMatchers/CMakeLists.txt
@@ -30,4 +30,9 @@
   clangTooling
   )
 
+target_link_libraries(ASTMatchersTests
+  PRIVATE
+  LLVMTestingSupport
+)
+
 add_subdirectory(Dynamic)
Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -13,10 +13,12 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/Host.h"
+#include "llvm/Testing/Support/SupportHelpers.h"
 #include "gtest/gtest.h"
 
 namespace clang {
 namespace ast_matchers {
+using internal::DynTypedMatcher;
 
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
@@ -171,6 +173,26 @@
   EXPECT_NE(nullptr, PT);
 }
 
+TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) {
+  auto M = DynTypedMatcher(decl());
+  EXPECT_FALSE(M.getTraversalKind().hasValue());
+
+  M = DynTypedMatcher(traverse(TK_AsIs, decl()));
+  EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) {
+  auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs);
+  EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) {
+  auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs).withTraversalKind(
+  TK_IgnoreUnlessSpelledInSource);
+  EXPECT_THAT(M.getTraversalKind(),
+  llvm::ValueIs(TK_IgnoreUnlessSpelledInSource));
+}
+
 TEST(IsInlineMatcher, IsInline) {
   EXPECT_TRUE(matches("void g(); inline void f();",
   functionDecl(isInline(), hasName("f";
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -136,6 +136,31 @@
   }
 };
 
+/// A matcher that specifies a particular \c TraversalKind.
+///
+/// The kind provided to the constructor overrides any kind that may be
+/// specified by the `InnerMatcher`.
+class DynTraversalMatcherImpl : public DynMatcherInterface {
+public:
+  explicit DynTraversalMatcherImpl(
+  clang::TraversalKind TK,
+  IntrusiveRefCntPtr InnerMatcher)
+  : TK(TK), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return this->InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  llvm::Optional TraversalKind() const override {
+return TK;
+  }
+
+private:
+  clang::TraversalKind TK;
+  IntrusiveRefCntPtr InnerMatcher;
+};
+
 } // namespace
 
 static llvm::ManagedStatic TrueMatcherInstance;
@@ -204,6 +229,14 @@
   return Copy;
 }
 
+DynTypedMatcher
+DynTypedMatcher::withTraversalKind(ast_type_traits::TraversalKind TK) {
+  auto Copy = *this;
+  Copy.Implementation =
+  new DynTraversalMatcherImpl(TK, std::move(Copy.Implementation));
+  return Copy;
+}
+
 DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) {
   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
 }
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -395,6 +395,12 @@
   ///   restricts the node types for \p Kind.
   DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
 
+  /// Return a matcher that that points to the same implementation, but sets the
+  ///   traversal kind.
+  ///
+  /// If the traversal kind is already set, then \c TK overrides it.
+  DynTypedMatcher withTraversalKind(TraversalKind TK);
+
   /// Returns true if the matcher matches the given \c DynNode.
   bool matches(const DynTypedNode , ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
@@ -458,6 +464,14 @@
   /// If it is not compatible, then this matcher will never match anything.
   template  Matcher unconditionalConvertTo() const;
 
+  /// Returns the \c 

[PATCH] D80685: [ASTMatchers] Add traversal-kind support to `DynTypedMatcher`

2020-05-28 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
ymandel marked 2 inline comments as done.
ymandel added inline comments.



Comment at: clang/lib/ASTMatchers/ASTMatchersInternal.cpp:234
+DynTypedMatcher::constructWithTraversalKind(DynTypedMatcher InnerMatcher,
+ast_type_traits::TraversalKind TK) 
{
+  InnerMatcher.Implementation =

gribozavr2 wrote:
> It might read better as an instance method on `DynTypedMatcher`: 
> `DynTypedMatcher::withTraversalKind()`. It is not unprecedented, see 
> `dynCastTo()`.
Agreed, thanks for the suggestion.



Comment at: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp:182
+  EXPECT_TRUE(TK.hasValue());
+  EXPECT_EQ(*TK, TK_AsIs);
+}

gribozavr2 wrote:
> Please use `EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));` (also 
> in tests below).
> 
> You'll need to include `llvm/Testing/Support/SupportHelpers.h`.
Thanks! This cleaned up the tests quite nicely.

I also updated the CMake file. Please let me know if that looks right to you. 
Cargo-culted from other cmake files...



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80685



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


[PATCH] D80685: [ASTMatchers] Add traversal-kind support to `DynTypedMatcher`

2020-05-28 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
ymandel updated this revision to Diff 266828.
ymandel marked 2 inline comments as done.
ymandel added a comment.
Herald added a subscriber: mgorny.

updated per comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80685

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
  clang/unittests/ASTMatchers/CMakeLists.txt

Index: clang/unittests/ASTMatchers/CMakeLists.txt
===
--- clang/unittests/ASTMatchers/CMakeLists.txt
+++ clang/unittests/ASTMatchers/CMakeLists.txt
@@ -30,4 +30,9 @@
   clangTooling
   )
 
+target_link_libraries(ASTMatchersTests
+  PRIVATE
+  LLVMTestingSupport
+)
+
 add_subdirectory(Dynamic)
Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -13,10 +13,12 @@
 #include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Support/Host.h"
+#include "llvm/Testing/Support/SupportHelpers.h"
 #include "gtest/gtest.h"
 
 namespace clang {
 namespace ast_matchers {
+using internal::DynTypedMatcher;
 
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
@@ -171,6 +173,26 @@
   EXPECT_NE(nullptr, PT);
 }
 
+TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) {
+  auto M = DynTypedMatcher(decl());
+  EXPECT_FALSE(M.getTraversalKind().hasValue());
+
+  M = DynTypedMatcher(traverse(TK_AsIs, decl()));
+  EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) {
+  auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs);
+  EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) {
+  auto M = DynTypedMatcher(decl()).withTraversalKind(TK_AsIs).withTraversalKind(
+  TK_IgnoreUnlessSpelledInSource);
+  EXPECT_THAT(M.getTraversalKind(),
+  llvm::ValueIs(TK_IgnoreUnlessSpelledInSource));
+}
+
 TEST(IsInlineMatcher, IsInline) {
   EXPECT_TRUE(matches("void g(); inline void f();",
   functionDecl(isInline(), hasName("f";
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -136,6 +136,31 @@
   }
 };
 
+/// A matcher that specifies a particular \c TraversalKind.
+///
+/// The kind provided to the constructor overrides any kind that may be
+/// specified by the `InnerMatcher`.
+class DynTraversalMatcherImpl : public DynMatcherInterface {
+public:
+  explicit DynTraversalMatcherImpl(
+  clang::TraversalKind TK,
+  IntrusiveRefCntPtr InnerMatcher)
+  : TK(TK), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return this->InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  llvm::Optional TraversalKind() const override {
+return TK;
+  }
+
+private:
+  clang::TraversalKind TK;
+  IntrusiveRefCntPtr InnerMatcher;
+};
+
 } // namespace
 
 static llvm::ManagedStatic TrueMatcherInstance;
@@ -204,6 +229,14 @@
   return Copy;
 }
 
+DynTypedMatcher
+DynTypedMatcher::withTraversalKind(ast_type_traits::TraversalKind TK) {
+  auto Copy = *this;
+  Copy.Implementation =
+  new DynTraversalMatcherImpl(TK, std::move(Copy.Implementation));
+  return Copy;
+}
+
 DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) {
   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
 }
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -395,6 +395,12 @@
   ///   restricts the node types for \p Kind.
   DynTypedMatcher dynCastTo(const ASTNodeKind Kind) const;
 
+  /// Return a matcher that that points to the same implementation, but sets the
+  ///   traversal kind.
+  ///
+  /// If the traversal kind is already set, then \c TK overrides it.
+  DynTypedMatcher withTraversalKind(TraversalKind TK);
+
   /// Returns true if the matcher matches the given \c DynNode.
   bool matches(const DynTypedNode , ASTMatchFinder *Finder,
BoundNodesTreeBuilder *Builder) const;
@@ -458,6 +464,14 @@
   /// If it is not compatible, then this matcher will never match anything.
   template  Matcher unconditionalConvertTo() const;
 
+  /// Returns the \c TraversalKind respected by calls to `match()`, if any.
+  ///
+  

[PATCH] D80685: [ASTMatchers] Add traversal-kind support to `DynTypedMatcher`

2020-05-28 Thread Dmitri Gribenko via Phabricator via cfe-commits
gribozavr2 accepted this revision.
gribozavr2 added inline comments.
This revision is now accepted and ready to land.



Comment at: clang/lib/ASTMatchers/ASTMatchersInternal.cpp:234
+DynTypedMatcher::constructWithTraversalKind(DynTypedMatcher InnerMatcher,
+ast_type_traits::TraversalKind TK) 
{
+  InnerMatcher.Implementation =

It might read better as an instance method on `DynTypedMatcher`: 
`DynTypedMatcher::withTraversalKind()`. It is not unprecedented, see 
`dynCastTo()`.



Comment at: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp:182
+  EXPECT_TRUE(TK.hasValue());
+  EXPECT_EQ(*TK, TK_AsIs);
+}

Please use `EXPECT_THAT(M.getTraversalKind(), llvm::ValueIs(TK_AsIs));` (also 
in tests below).

You'll need to include `llvm/Testing/Support/SupportHelpers.h`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D80685



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


[PATCH] D80685: [ASTMatchers] Add traversal-kind support to `DynTypedMatcher`

2020-05-27 Thread Yitzhak Mandelbaum via Phabricator via cfe-commits
ymandel created this revision.
ymandel added reviewers: gribozavr, steveire.
Herald added a project: clang.

This patch exposes `TraversalKind` support in the `DynTypedMatcher` API. While
previously, the `match` method supported traversal logic, it was not possible to
set or get the traversal kind.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D80685

Files:
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/lib/ASTMatchers/ASTMatchersInternal.cpp
  clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
===
--- clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersInternalTest.cpp
@@ -17,6 +17,7 @@
 
 namespace clang {
 namespace ast_matchers {
+using internal::DynTypedMatcher;
 
 #if GTEST_HAS_DEATH_TEST
 TEST(HasNameDeathTest, DiesOnEmptyName) {
@@ -171,6 +172,34 @@
   EXPECT_NE(nullptr, PT);
 }
 
+TEST(DynTypedMatcherTest, TraversalKindForwardsToImpl) {
+  auto M = DynTypedMatcher(decl());
+  EXPECT_FALSE(M.getTraversalKind().hasValue());
+
+  M = DynTypedMatcher(traverse(TK_AsIs, decl()));
+  llvm::Optional TK = M.getTraversalKind();
+  EXPECT_TRUE(TK.hasValue());
+  EXPECT_EQ(*TK, TK_AsIs);
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindSetsTK) {
+  auto M = DynTypedMatcher::constructWithTraversalKind(DynTypedMatcher(decl()),
+   TK_AsIs);
+  llvm::Optional TK = M.getTraversalKind();
+  EXPECT_TRUE(TK.hasValue());
+  EXPECT_EQ(*TK, TK_AsIs);
+}
+
+TEST(DynTypedMatcherTest, ConstructWithTraversalKindOverridesNestedTK) {
+  auto M = DynTypedMatcher::constructWithTraversalKind(DynTypedMatcher(decl()),
+   TK_AsIs);
+  auto M2 = DynTypedMatcher::constructWithTraversalKind(
+  M, TK_IgnoreUnlessSpelledInSource);
+  llvm::Optional TK = M2.getTraversalKind();
+  EXPECT_TRUE(TK.hasValue());
+  EXPECT_EQ(*TK, TK_IgnoreUnlessSpelledInSource);
+}
+
 TEST(IsInlineMatcher, IsInline) {
   EXPECT_TRUE(matches("void g(); inline void f();",
   functionDecl(isInline(), hasName("f";
Index: clang/lib/ASTMatchers/ASTMatchersInternal.cpp
===
--- clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -136,6 +136,31 @@
   }
 };
 
+/// A matcher that specifies a particular \c TraversalKind.
+///
+/// The kind provided to the constructor overrides any kind that may be
+/// specified by the `InnerMatcher`.
+class DynTraversalMatcherImpl : public DynMatcherInterface {
+public:
+  explicit DynTraversalMatcherImpl(
+  clang::TraversalKind TK,
+  IntrusiveRefCntPtr InnerMatcher)
+  : TK(TK), InnerMatcher(std::move(InnerMatcher)) {}
+
+  bool dynMatches(const DynTypedNode , ASTMatchFinder *Finder,
+  BoundNodesTreeBuilder *Builder) const override {
+return this->InnerMatcher->dynMatches(DynNode, Finder, Builder);
+  }
+
+  llvm::Optional TraversalKind() const override {
+return TK;
+  }
+
+private:
+  clang::TraversalKind TK;
+  IntrusiveRefCntPtr InnerMatcher;
+};
+
 } // namespace
 
 static llvm::ManagedStatic TrueMatcherInstance;
@@ -204,6 +229,14 @@
   return Copy;
 }
 
+DynTypedMatcher
+DynTypedMatcher::constructWithTraversalKind(DynTypedMatcher InnerMatcher,
+ast_type_traits::TraversalKind TK) {
+  InnerMatcher.Implementation =
+  new DynTraversalMatcherImpl(TK, std::move(InnerMatcher.Implementation));
+  return InnerMatcher;
+}
+
 DynTypedMatcher DynTypedMatcher::trueMatcher(ASTNodeKind NodeKind) {
   return DynTypedMatcher(NodeKind, NodeKind, &*TrueMatcherInstance);
 }
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -379,6 +379,12 @@
   constructRestrictedWrapper(const DynTypedMatcher ,
  ASTNodeKind RestrictKind);
 
+  /// Creates a new matcher that is identical to the old one, but sets the
+  /// traversal kind. If `InnerMatcher` had already set a traversal kind, then
+  /// the new one overrides it.
+  static DynTypedMatcher
+  constructWithTraversalKind(DynTypedMatcher InnerMatcher, TraversalKind TK);
+
   /// Get a "true" matcher for \p NodeKind.
   ///
   /// It only checks that the node is of the right kind.
@@ -458,6 +464,14 @@
   /// If it is not compatible, then this matcher will never match anything.
   template  Matcher unconditionalConvertTo() const;
 
+  /// Returns the \c TraversalKind respected by calls to `match()`, if any.
+  ///
+  /// Most matchers will not have a traversal kind set, instead relying on the
+  /// surrounding context. For those, \c