steveire created this revision.
steveire added a reviewer: aaron.ballman.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

These overloads make it possible to wrap unless(), anyOf(), has() etc
with the traverse matcher.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71977

Files:
  clang/include/clang/ASTMatchers/ASTMatchers.h
  clang/include/clang/ASTMatchers/ASTMatchersInternal.h
  clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp

Index: clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
===================================================================
--- clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -1612,6 +1612,87 @@
       matches(VarDeclCode,
               traverse(ast_type_traits::TK_IgnoreImplicitCastsAndParentheses,
                        Matcher)));
+
+  EXPECT_TRUE(
+      matches(VarDeclCode, decl(traverse(ast_type_traits::TK_AsIs,
+                                         anyOf(cxxRecordDecl(), varDecl())))));
+
+  EXPECT_TRUE(matches(VarDeclCode,
+                      floatLiteral(traverse(ast_type_traits::TK_AsIs,
+                                            hasParent(implicitCastExpr())))));
+
+  EXPECT_TRUE(matches(
+      VarDeclCode,
+      floatLiteral(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                            hasParent(varDecl())))));
+
+  EXPECT_TRUE(
+      matches(VarDeclCode,
+              varDecl(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                               unless(parmVarDecl())))));
+
+  EXPECT_TRUE(notMatches(
+      VarDeclCode,
+      varDecl(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                       has(implicitCastExpr())))));
+
+  EXPECT_TRUE(matches(VarDeclCode, varDecl(traverse(ast_type_traits::TK_AsIs,
+                                                    has(implicitCastExpr())))));
+
+  EXPECT_TRUE(notMatches(
+      VarDeclCode,
+      varDecl(has(traverse(ast_type_traits::TK_AsIs, floatLiteral())))));
+
+  EXPECT_TRUE(matches(
+      VarDeclCode,
+      functionDecl(traverse(ast_type_traits::TK_AsIs, hasName("foo")))));
+
+  EXPECT_TRUE(matches(
+      VarDeclCode,
+      functionDecl(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                            hasName("foo")))));
+
+  EXPECT_TRUE(
+      matches(VarDeclCode, functionDecl(traverse(ast_type_traits::TK_AsIs,
+                                                 hasAnyName("foo", "bar")))));
+
+  EXPECT_TRUE(matches(
+      VarDeclCode,
+      functionDecl(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                            hasAnyName("foo", "bar")))));
+
+  EXPECT_TRUE(
+      matches(R"cpp(
+void foo(int a)
+{
+  int i = 3.0 + a;
+}
+void bar()
+{
+  foo(7.0);
+}
+)cpp",
+              callExpr(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                                hasArgument(0, floatLiteral())))));
+
+  EXPECT_TRUE(
+      matches(R"cpp(
+void foo(int a)
+{
+  int i = 3.0 + a;
+}
+void bar()
+{
+  foo(7.0);
+}
+)cpp",
+              callExpr(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                                hasAnyArgument(floatLiteral())))));
+
+  EXPECT_TRUE(
+      matches(VarDeclCode,
+              varDecl(traverse(ast_type_traits::TK_IgnoreUnlessSpelledInSource,
+                               hasType(builtinType())))));
 }
 
 TEST(Traversal, traverseMatcherNesting) {
Index: clang/include/clang/ASTMatchers/ASTMatchersInternal.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchersInternal.h
+++ clang/include/clang/ASTMatchers/ASTMatchersInternal.h
@@ -1129,6 +1129,23 @@
              TemplateSpecializationType, TemplateTypeParmType, TypedefType,
              UnresolvedUsingType, ObjCIvarRefExpr>;
 
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+          typename T, typename ToTypes>
+class ArgumentAdaptingMatcherFuncAdaptor {
+public:
+  explicit ArgumentAdaptingMatcherFuncAdaptor(const Matcher<T> &InnerMatcher)
+      : InnerMatcher(InnerMatcher) {}
+
+  using ReturnTypes = ToTypes;
+
+  template <typename To> operator Matcher<To>() const {
+    return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
+  }
+
+private:
+  const Matcher<T> InnerMatcher;
+};
+
 /// Converts a \c Matcher<T> to a matcher of desired type \c To by
 /// "adapting" a \c To into a \c T.
 ///
@@ -1146,28 +1163,16 @@
           typename FromTypes = AdaptativeDefaultFromTypes,
           typename ToTypes = AdaptativeDefaultToTypes>
 struct ArgumentAdaptingMatcherFunc {
-  template <typename T> class Adaptor {
-  public:
-    explicit Adaptor(const Matcher<T> &InnerMatcher)
-        : InnerMatcher(InnerMatcher) {}
-
-    using ReturnTypes = ToTypes;
-
-    template <typename To> operator Matcher<To>() const {
-      return Matcher<To>(new ArgumentAdapterT<To, T>(InnerMatcher));
-    }
-
-  private:
-    const Matcher<T> InnerMatcher;
-  };
-
   template <typename T>
-  static Adaptor<T> create(const Matcher<T> &InnerMatcher) {
-    return Adaptor<T>(InnerMatcher);
+  static ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
+  create(const Matcher<T> &InnerMatcher) {
+    return ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>(
+        InnerMatcher);
   }
 
   template <typename T>
-  Adaptor<T> operator()(const Matcher<T> &InnerMatcher) const {
+  ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>
+  operator()(const Matcher<T> &InnerMatcher) const {
     return create(InnerMatcher);
   }
 };
@@ -1194,6 +1199,24 @@
   }
 };
 
+template <typename MatcherType> class TraversalWrapper {
+public:
+  TraversalWrapper(ast_type_traits::TraversalKind TK,
+                   const MatcherType &InnerMatcher)
+      : TK(TK), InnerMatcher(InnerMatcher) {}
+
+  template <typename T> operator internal::Matcher<T>() {
+    return internal::DynTypedMatcher::constructRestrictedWrapper(
+               new internal::TraversalMatcher<T>(TK, InnerMatcher),
+               ast_type_traits::ASTNodeKind::getFromNodeKind<T>())
+        .template unconditionalConvertTo<T>();
+  }
+
+private:
+  ast_type_traits::TraversalKind TK;
+  MatcherType InnerMatcher;
+};
+
 /// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be
 /// created from N parameters p1, ..., pN (of type P1, ..., PN) and
 /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN)
Index: clang/include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- clang/include/clang/ASTMatchers/ASTMatchers.h
+++ clang/include/clang/ASTMatchers/ASTMatchers.h
@@ -714,6 +714,51 @@
       .template unconditionalConvertTo<T>();
 }
 
+template <typename... T>
+internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>
+traverse(ast_type_traits::TraversalKind TK,
+         const internal::VariadicOperatorMatcher<T...> &InnerMatcher) {
+  return internal::TraversalWrapper<internal::VariadicOperatorMatcher<T...>>(
+      TK, InnerMatcher);
+}
+
+template <template <typename ToArg, typename FromArg> class ArgumentAdapterT,
+          typename T, typename ToTypes>
+internal::TraversalWrapper<
+    internal::ArgumentAdaptingMatcherFuncAdaptor<ArgumentAdapterT, T, ToTypes>>
+traverse(ast_type_traits::TraversalKind TK,
+         const internal::ArgumentAdaptingMatcherFuncAdaptor<
+             ArgumentAdapterT, T, ToTypes> &InnerMatcher) {
+  return internal::TraversalWrapper<internal::ArgumentAdaptingMatcherFuncAdaptor<
+      ArgumentAdapterT, T, ToTypes>>(TK, InnerMatcher);
+}
+
+template <template <typename T, typename P1> class MatcherT, typename P1,
+          typename ReturnTypesF>
+internal::TraversalWrapper<
+    internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>
+traverse(
+    ast_type_traits::TraversalKind TK,
+    const internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>
+        &InnerMatcher) {
+  return internal::TraversalWrapper<
+      internal::PolymorphicMatcherWithParam1<MatcherT, P1, ReturnTypesF>>(
+      TK, InnerMatcher);
+}
+
+template <template <typename T, typename P1, typename P2> class MatcherT,
+          typename P1, typename P2, typename ReturnTypesF>
+internal::TraversalWrapper<
+    internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>
+traverse(
+    ast_type_traits::TraversalKind TK,
+    const internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>
+        &InnerMatcher) {
+  return internal::TraversalWrapper<
+      internal::PolymorphicMatcherWithParam2<MatcherT, P1, P2, ReturnTypesF>>(
+      TK, InnerMatcher);
+}
+
 /// Matches expressions that match InnerMatcher after any implicit AST
 /// nodes are stripped off.
 ///
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to