Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -4353,7 +4353,7 @@ For ObjectiveC, given @interface I - (void) f:(int) y; @end - void foo(I *i) { [i f:12] } + void foo(I *i) { [i f:12]; } objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) matches [i f:12] @@ -4706,7 +4706,7 @@ For ObjectiveC, given @interface I - (void) f:(int) y; @end - void foo(I *i) { [i f:12] } + void foo(I *i) { [i f:12]; } objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) matches [i f:12] @@ -5272,7 +5272,7 @@
Matches any parameter of a function declaration. ++ Matches any parameter of a function or ObjC method declaration. Does not match the 'this' parameter of a method. @@ -5321,7 +5321,7 @@- Matcher<FunctionDecl> hasParameter unsigned N, Matcher<ParmVarDecl> InnerMatcher @@ -5687,6 +5693,20 @@ Matches the n'th parameter of a function declaration. +@@ -5659,7 +5665,7 @@ For ObjectiveC, given @interface I - (void) f:(int) y; @end - void foo(I *i) { [i f:12] } + void foo(I *i) { [i f:12]; } objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) matches [i f:12] Matches the n'th parameter of a function or ObjC method declaration. Given class X { void f(int x) {} }; @@ -5329,6 +5329,12 @@ matches f(int x) {} with hasParameter(...) matching int x + +For ObjectiveC, given + @interface I - (void) f:(int) y; @end + +the matcher {@code objcMethodDecl(hasAnyArgument(hasName("y")))} +matches the declaration of parameter {@code y}.+ Matcher<ObjCMethodDecl> hasAnyParameter Matcher<ParmVarDecl> InnerMatcher + + Matches any parameter of a function or ObjC method declaration. + +Does not match the 'this' parameter of a method. + +Given + class X { void f(int x, int y, int z) {} }; +cxxMethodDecl(hasAnyParameter(hasName("y"))) + matches f(int x, int y, int z) {} +with hasAnyParameter(...) + matching int y +Matcher<OpaqueValueExpr> hasSourceExpression Matcher<Expr> InnerMatcher Matches if the cast's source expression or opaque value's source expression matches the given matcher. Index: include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- include/clang/ASTMatchers/ASTMatchers.h +++ include/clang/ASTMatchers/ASTMatchers.h @@ -3466,7 +3466,8 @@ return Node.requiresZeroInitialization(); } -/// \brief Matches the n'th parameter of a function declaration. +/// \brief Matches the n'th parameter of a function or an ObjC method +/// declaration. /// /// Given /// \code @@ -3476,12 +3477,31 @@ /// matches f(int x) {} /// with hasParameter(...) /// matching int x -AST_MATCHER_P2(FunctionDecl, hasParameter, - unsigned, N, internal::Matcher, - InnerMatcher) { - return (N < Node.getNumParams() && - InnerMatcher.matches( - *Node.getParamDecl(N), Finder, Builder)); +/// +/// For ObjectiveC, given +/// \code +/// @interface I - (void) f:(int) y; @end +/// \endcode +// +/// the matcher {@code objcMethodDecl(hasParameter(0, hasName("y")))} +/// matches the declaration of method {@code f} with {@code hasParameter} +/// matching {@code y}. +AST_POLYMORPHIC_MATCHER_P2(hasParameter, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + ObjCMethodDecl), + unsigned, N, internal::Matcher , + InnerMatcher) { + unsigned NumParams; + const ParmVarDecl* Decl; + if (const auto *FD = dyn_cast (&Node)) { + NumParams = FD->getNumParams(); + Decl = FD->getParamDecl(N); + } else { + const auto *OM = dyn_cast (&Node); + NumParams = OM->param_size(); + Decl = OM->parameters()[N]; + } + return (N < NumParams && InnerMatcher.matches(*Decl, Finder, Builder)); } /// \brief Matches all arguments and their respective ParmVarDecl. @@ -3538,7 +3558,7 @@ return Matched; } -/// \brief Matches any parameter of a function declaration. +/// \brief Matches any parameter of a function or ObjC method declaration. /// /// Does not match the 'this' parameter of a method. /// @@ -3550,8 +3570,20 @@ /// matches f(int x, int y, int z) {} /// with hasAnyParameter(...) /// matching int y -AST_MATCHER_P(FunctionDecl, hasAnyParameter, - internal::Matcher , InnerMatcher) { +/// +/// For ObjectiveC, given +/// \code +/// @interface I - (void) f:(int) y; @end +/// \endcode +// +/// the matcher {@code objcMethodDecl(hasAnyParameter(hasName("y")))} +/// matches the declaration of method {@code f} with {@code hasParameter} +/// matching {@code y}. +AST_POLYMORPHIC_MATCHER_P(hasAnyParameter, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + ObjCMethodDecl), + internal::Matcher , + InnerMatcher) { return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(), Node.param_end(), Finder, Builder); } Index: lib/Analysis/BodyFarm.cpp =================================================================== --- lib/Analysis/BodyFarm.cpp +++ lib/Analysis/BodyFarm.cpp @@ -314,6 +314,7 @@ /// } /// \endcode static Stmt *create_call_once(ASTContext &C, const FunctionDecl *D) { + DEBUG(llvm::dbgs() << "Generating body for call_once\n"); // We need at least two parameters. Index: unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -539,6 +539,8 @@ cxxMethodDecl(hasParameter(0, varDecl())))); EXPECT_TRUE(notMatches("class X { void x(int) {} };", cxxMethodDecl(hasParameter(0, hasName("x"))))); + EXPECT_TRUE(matches("@interface I -(void)f:(int) x; @end", + objcMethodDecl(hasParameter(0, hasName("x"))))); } TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) { @@ -568,6 +570,8 @@ EXPECT_TRUE(matches( "class Y {}; class X { void x(Y y, X x) {} };", cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X"))))))); + EXPECT_TRUE(matches("@interface I -(void)f:(int) x; @end", + objcMethodDecl(hasAnyParameter(hasName("x"))))); } TEST(Returns, MatchesReturnTypes) {