Index: cfe/trunk/docs/LibASTMatchersReference.html =================================================================== --- cfe/trunk/docs/LibASTMatchersReference.html +++ cfe/trunk/docs/LibASTMatchersReference.html @@ -4854,6 +4854,25 @@ </pre></td></tr> +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CXXUnresolvedConstructExpr.html">CXXUnresolvedConstructExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call +expression, or an ObjC-message-send expression. + +Given + void x(int, int, int) { int y; x(1, y, 42); } +callExpr(hasAnyArgument(declRefExpr())) + matches x(1, y, 42) +with hasAnyArgument(...) + matching y + +For ObjectiveC, given + @interface I - (void) f:(int) y; @end + void foo(I *i) { [i f:12]; } +objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) + matches [i f:12] +</pre></td></tr> + + <tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1CallExpr.html">CallExpr</a>></td><td class="name" onclick="toggle('callee1')"><a name="callee1Anchor">callee</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Decl.html">Decl</a>> InnerMatcher</td></tr> <tr><td colspan="4" class="doc" id="callee1"><pre>Matches if the call expression's callee's declaration matches the given matcher. @@ -5938,8 +5957,8 @@ </pre></td></tr> -<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument2')"><a name="hasAnyArgument2Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> -<tr><td colspan="4" class="doc" id="hasAnyArgument2"><pre>Matches any argument of a call expression or a constructor call +<tr><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1ObjCMessageExpr.html">ObjCMessageExpr</a>></td><td class="name" onclick="toggle('hasAnyArgument3')"><a name="hasAnyArgument3Anchor">hasAnyArgument</a></td><td>Matcher<<a href="http://clang.llvm.org/doxygen/classclang_1_1Expr.html">Expr</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="hasAnyArgument3"><pre>Matches any argument of a call expression or a constructor call expression, or an ObjC-message-send expression. Given Index: cfe/trunk/include/clang/AST/ExprCXX.h =================================================================== --- cfe/trunk/include/clang/AST/ExprCXX.h +++ cfe/trunk/include/clang/AST/ExprCXX.h @@ -3426,16 +3426,22 @@ unsigned arg_size() const { return NumArgs; } using arg_iterator = Expr **; + using arg_range = llvm::iterator_range<arg_iterator>; arg_iterator arg_begin() { return getTrailingObjects<Expr *>(); } arg_iterator arg_end() { return arg_begin() + NumArgs; } + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } using const_arg_iterator = const Expr* const *; + using const_arg_range = llvm::iterator_range<const_arg_iterator>; const_arg_iterator arg_begin() const { return getTrailingObjects<Expr *>(); } const_arg_iterator arg_end() const { return arg_begin() + NumArgs; } + const_arg_range arguments() const { + return const_arg_range(arg_begin(), arg_end()); + } Expr *getArg(unsigned I) { assert(I < NumArgs && "Argument index out-of-range"); Index: cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h +++ cfe/trunk/include/clang/ASTMatchers/ASTMatchers.h @@ -3565,9 +3565,9 @@ /// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) /// matches [i f:12] AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, - AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr, - ObjCMessageExpr), + AST_POLYMORPHIC_SUPPORTED_TYPES( + CallExpr, CXXConstructExpr, + CXXUnresolvedConstructExpr, ObjCMessageExpr), internal::Matcher<Expr>, InnerMatcher) { for (const Expr *Arg : Node.arguments()) { BoundNodesTreeBuilder Result(*Builder); Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -406,9 +406,22 @@ auto HasArgumentY = hasAnyArgument( ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y")))))); StatementMatcher CallArgumentY = callExpr(HasArgumentY); + StatementMatcher CtorArgumentY = cxxConstructExpr(HasArgumentY); + StatementMatcher UnresolvedCtorArgumentY = + cxxUnresolvedConstructExpr(HasArgumentY); StatementMatcher ObjCCallArgumentY = objcMessageExpr(HasArgumentY); EXPECT_TRUE(matches("void x(int, int) { int y; x(1, y); }", CallArgumentY)); EXPECT_TRUE(matches("void x(int, int) { int y; x(y, 42); }", CallArgumentY)); + EXPECT_TRUE(matches("struct Y { Y(int, int); };" + "void x() { int y; (void)Y(1, y); }", + CtorArgumentY)); + EXPECT_TRUE(matches("struct Y { Y(int, int); };" + "void x() { int y; (void)Y(y, 42); }", + CtorArgumentY)); + EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(1, y); }", + UnresolvedCtorArgumentY)); + EXPECT_TRUE(matches("template <class Y> void x() { int y; (void)Y(y, 42); }", + UnresolvedCtorArgumentY)); EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) y; @end " "void x(I* i) { int y; [i f:y]; }", ObjCCallArgumentY)); @@ -416,6 +429,12 @@ "void x(I* i) { int z; [i f:z]; }", ObjCCallArgumentY)); EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY)); + EXPECT_TRUE(notMatches("struct Y { Y(int, int); };" + "void x() { int y; (void)Y(1, 2); }", + CtorArgumentY)); + EXPECT_TRUE(notMatches("template <class Y>" + "void x() { int y; (void)Y(1, 2); }", + UnresolvedCtorArgumentY)); StatementMatcher ImplicitCastedArgument = callExpr( hasAnyArgument(implicitCastExpr()));