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