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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits