fowles created this revision. fowles added a reviewer: klimek. fowles added a subscriber: cfe-commits.
Add an argumentsAre matcher https://reviews.llvm.org/D28260 Files: include/clang/ASTMatchers/ASTMatchers.h unittests/ASTMatchers/ASTMatchersTraversalTest.cpp Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -375,6 +375,14 @@ EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex)); } +TEST(Matcher, ArgumentsAre) { + StatementMatcher Call = callExpr(argumentsAre(declRefExpr(), declRefExpr())); + + EXPECT_TRUE(notMatches("void f(int x) { f(x); }", Call)); + EXPECT_TRUE(matches("void f(int x, int y) { f(x, y); }", Call)); + EXPECT_TRUE(notMatches("void f(int x, int y, int z) { f(x, y, z); }", Call)); +} + TEST(Matcher, AnyArgument) { StatementMatcher CallArgumentY = callExpr( hasAnyArgument( Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3055,6 +3055,34 @@ *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); } +namespace internal { +inline auto argumentsAreImpl(int n) -> decltype(argumentCountIs(n)) { + return argumentCountIs(n); +} + +template <typename First, typename... Rest> +auto argumentsAreImpl(int n, First &&first, Rest &&... rest) + -> decltype(allOf(hasArgument(n, std::forward<First>(first)), + argumentsAreImpl(n + 1, std::forward<Rest>(rest)...))) { + return allOf(hasArgument(n, std::forward<First>(first)), + argumentsAreImpl(n + 1, std::forward<Rest>(rest)...)); +} +} // end namespace internal + +/// \brief Matches all the arguments of a call expression or a constructor +/// call expression. +/// +/// Example matches the call to f2, but not f1 or f3. +/// (matcher = callExpr(argumentsAre(declRefExpr(), declRefExpr()))) +/// \code +/// void x(int a, int b, int c) { f1(a); f2(a, b); f3(a, b, c); } +/// \endcode +template <typename... T> +auto argumentsAre(T &&... t) + -> decltype(internal::argumentsAreImpl(0, std::forward<T>(t)...)) { + return internal::argumentsAreImpl(0, std::forward<T>(t)...); +} + /// \brief Matches declaration statements that contain a specific number of /// declarations. ///
Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -375,6 +375,14 @@ EXPECT_TRUE(notMatches("void x(int) { int y; x(y); }", WrongIndex)); } +TEST(Matcher, ArgumentsAre) { + StatementMatcher Call = callExpr(argumentsAre(declRefExpr(), declRefExpr())); + + EXPECT_TRUE(notMatches("void f(int x) { f(x); }", Call)); + EXPECT_TRUE(matches("void f(int x, int y) { f(x, y); }", Call)); + EXPECT_TRUE(notMatches("void f(int x, int y, int z) { f(x, y, z); }", Call)); +} + TEST(Matcher, AnyArgument) { StatementMatcher CallArgumentY = callExpr( hasAnyArgument( Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3055,6 +3055,34 @@ *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); } +namespace internal { +inline auto argumentsAreImpl(int n) -> decltype(argumentCountIs(n)) { + return argumentCountIs(n); +} + +template <typename First, typename... Rest> +auto argumentsAreImpl(int n, First &&first, Rest &&... rest) + -> decltype(allOf(hasArgument(n, std::forward<First>(first)), + argumentsAreImpl(n + 1, std::forward<Rest>(rest)...))) { + return allOf(hasArgument(n, std::forward<First>(first)), + argumentsAreImpl(n + 1, std::forward<Rest>(rest)...)); +} +} // end namespace internal + +/// \brief Matches all the arguments of a call expression or a constructor +/// call expression. +/// +/// Example matches the call to f2, but not f1 or f3. +/// (matcher = callExpr(argumentsAre(declRefExpr(), declRefExpr()))) +/// \code +/// void x(int a, int b, int c) { f1(a); f2(a, b); f3(a, b, c); } +/// \endcode +template <typename... T> +auto argumentsAre(T &&... t) + -> decltype(internal::argumentsAreImpl(0, std::forward<T>(t)...)) { + return internal::argumentsAreImpl(0, std::forward<T>(t)...); +} + /// \brief Matches declaration statements that contain a specific number of /// declarations. ///
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits