From e91c6a13f61ccf1df6e5f9738750c7baaf344156 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 7 Mar 2018 02:32:44 +0000 Subject: [PATCH] [ASTMatcher] Extend hasAnyArgument to ObjCMessageExpr Currently hasArgument works with both ObjC messages and function calls, but not hasAnyArgument. This patch fixes that discrepancy, as it's often more convenient to use hasAnyArgument. On a more general note, it would be great to have a common superclass for objc-call and function call, and a matcher matching that, but that's probably a job for another commit. Differential Revision: https://reviews.llvm.org/D44169 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@326865 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/LibASTMatchersReference.html | 35 +++++++++++++++++-- include/clang/ASTMatchers/ASTMatchers.h | 13 +++++-- .../ASTMatchers/ASTMatchersTraversalTest.cpp | 13 +++++-- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index 0a9fcceb0b..21e6f918ed 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -4342,7 +4342,7 @@ and parmVarDecl(...) Matcher<CXXConstructExpr>hasAnyArgumentMatcher<Expr> InnerMatcher
Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
 
 Given
   void x(int, int, int) { int y; x(1, y, 42); }
@@ -4350,6 +4350,12 @@ 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]
 
@@ -4689,7 +4695,7 @@ and parmVarDecl(...) Matcher<CallExpr>hasAnyArgumentMatcher<Expr> InnerMatcher
Matches any argument of a call expression or a constructor call
-expression.
+expression, or an ObjC-message-send expression.
 
 Given
   void x(int, int, int) { int y; x(1, y, 42); }
@@ -4697,6 +4703,12 @@ 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]
 
@@ -5634,6 +5646,25 @@ nestedNameSpecifier(specifiesType( +Matcher<ObjCMessageExpr>hasAnyArgumentMatcher<Expr> InnerMatcher +
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]
+
+ + Matcher<ObjCMessageExpr>hasArgumentunsigned N, Matcher<Expr> InnerMatcher
Matches the n'th argument of a call expression or a constructor
 call expression.
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index 6279172732..30ec133df3 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -3412,7 +3412,7 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
 }
 
 /// \brief Matches any argument of a call expression or a constructor call
-/// expression.
+/// expression, or an ObjC-message-send expression.
 ///
 /// Given
 /// \code
@@ -3422,9 +3422,18 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) {
 ///   matches x(1, y, 42)
 /// with hasAnyArgument(...)
 ///   matching y
+///
+/// For ObjectiveC, given
+/// \code
+///   @interface I - (void) f:(int) y; @end
+///   void foo(I *i) { [i f:12]; }
+/// \endcode
+/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12))))
+///   matches [i f:12]
 AST_POLYMORPHIC_MATCHER_P(hasAnyArgument,
                           AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr,
-                                                          CXXConstructExpr),
+                                                          CXXConstructExpr,
+                                                          ObjCMessageExpr),
                           internal::Matcher, InnerMatcher) {
   for (const Expr *Arg : Node.arguments()) {
     BoundNodesTreeBuilder Result(*Builder);
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index e699e19262..a5381842f4 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -403,11 +403,18 @@ TEST(Matcher, Argument) {
 }
 
 TEST(Matcher, AnyArgument) {
-  StatementMatcher CallArgumentY = callExpr(
-    hasAnyArgument(
-      ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y")))))));
+  auto HasArgumentY = hasAnyArgument(
+      ignoringParenImpCasts(declRefExpr(to(varDecl(hasName("y"))))));
+  StatementMatcher CallArgumentY = callExpr(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(matchesObjC("@interface I -(void)f:(int) y; @end "
+                          "void x(I* i) { int y; [i f:y]; }",
+                          ObjCCallArgumentY));
+  EXPECT_FALSE(matchesObjC("@interface I -(void)f:(int) z; @end "
+                           "void x(I* i) { int z; [i f:z]; }",
+                           ObjCCallArgumentY));
   EXPECT_TRUE(notMatches("void x(int, int) { x(1, 2); }", CallArgumentY));
 
   StatementMatcher ImplicitCastedArgument = callExpr(
-- 
2.40.0