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 +auto argumentsAreImpl(int n, First &&first, Rest &&... rest) + -> decltype(allOf(hasArgument(n, std::forward(first)), + argumentsAreImpl(n + 1, std::forward(rest)...))) { + return allOf(hasArgument(n, std::forward(first)), + argumentsAreImpl(n + 1, std::forward(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 +auto argumentsAre(T &&... t) + -> decltype(internal::argumentsAreImpl(0, std::forward(t)...)) { + return internal::argumentsAreImpl(0, std::forward(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(