From: George Karpenkov Date: Wed, 16 May 2018 22:47:03 +0000 (+0000) Subject: [ASTMatchers] Introduce a blockDecl matcher for matching block declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9a64e8cc615f59592630d53580af94f735578ef3;p=clang [ASTMatchers] Introduce a blockDecl matcher for matching block declarations Blocks can be matched just as well as functions or Objective-C methods. Differential Revision: https://reviews.llvm.org/D46980 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@332545 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/docs/LibASTMatchersReference.html b/docs/LibASTMatchersReference.html index bc58e3d9a6..6c67fd5b60 100644 --- a/docs/LibASTMatchersReference.html +++ b/docs/LibASTMatchersReference.html @@ -124,6 +124,18 @@ accessSpecDecl() +Matcher<Decl>blockDeclMatcher<BlockDecl>... +
Matches block declarations.
+
+Example matches the declaration of the nameless block printing an input
+integer.
+
+  myFunc(^(int p) {
+    printf("%d", p);
+  })
+
+ + Matcher<Decl>classTemplateDeclMatcher<ClassTemplateDecl>...
Matches C++ class template declarations.
 
@@ -4352,6 +4364,55 @@ Example matches b (matcher = binaryOperator(hasRHS()))
 
+Matcher<BlockDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher +
Matches any parameter of a function or an ObjC method declaration or a
+block.
+
+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
+
+For ObjectiveC, given
+  @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+
+For blocks, given
+  b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
+
+ + +Matcher<BlockDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher +
Matches the n'th parameter of a function or an ObjC method
+declaration or a block.
+
+Given
+  class X { void f(int x) {} };
+cxxMethodDecl(hasParameter(0, hasType(varDecl())))
+  matches f(int x) {}
+with hasParameter(...)
+  matching int x
+
+For ObjectiveC, given
+  @interface I - (void) f:(int) y; @end
+
+the matcher objcMethodDecl(hasParameter(0, hasName("y")))
+matches the declaration of method f with hasParameter
+matching y.
+
+ + Matcher<BlockPointerTypeLoc>pointeeLocMatcher<TypeLoc>
Narrows PointerType (and similar) matchers to those where the
 pointee matches a given matcher.
@@ -5336,7 +5397,8 @@ matches 'int x = 0' in
 
 
 Matcher<FunctionDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher
-
Matches any parameter of a function or ObjC method declaration.
+
Matches any parameter of a function or an ObjC method declaration or a
+block.
 
 Does not match the 'this' parameter of a method.
 
@@ -5353,6 +5415,13 @@ For ObjectiveC, given
 the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
 matches the declaration of method f with hasParameter
 matching y.
+
+For blocks, given
+  b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
 
@@ -5393,7 +5462,7 @@ with compoundStmt() Matcher<FunctionDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher
Matches the n'th parameter of a function or an ObjC method
-declaration.
+declaration or a block.
 
 Given
   class X { void f(int x) {} };
@@ -5767,7 +5836,8 @@ matches the [webView ...] message invocation.
 
 
 Matcher<ObjCMethodDecl>hasAnyParameterMatcher<ParmVarDecl> InnerMatcher
-
Matches any parameter of a function or ObjC method declaration.
+
Matches any parameter of a function or an ObjC method declaration or a
+block.
 
 Does not match the 'this' parameter of a method.
 
@@ -5784,12 +5854,19 @@ For ObjectiveC, given
 the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
 matches the declaration of method f with hasParameter
 matching y.
+
+For blocks, given
+  b = ^(int y) { printf("%d", y) };
+
+the matcher blockDecl(hasAnyParameter(hasName("y")))
+matches the declaration of the block b with hasParameter
+matching y.
 
Matcher<ObjCMethodDecl>hasParameterunsigned N, Matcher<ParmVarDecl> InnerMatcher
Matches the n'th parameter of a function or an ObjC method
-declaration.
+declaration or a block.
 
 Given
   class X { void f(int x) {} };
diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h
index b1b3f7269e..c9e182172c 100644
--- a/include/clang/ASTMatchers/ASTMatchers.h
+++ b/include/clang/ASTMatchers/ASTMatchers.h
@@ -1227,6 +1227,19 @@ extern const internal::VariadicDynCastAllOfMatcher
 extern const internal::VariadicDynCastAllOfMatcher
     objcMethodDecl;
 
+/// Matches block declarations.
+/// 
+/// Example matches the declaration of the nameless block printing an input
+/// integer.
+///
+/// \code
+///   myFunc(^(int p) {
+///     printf("%d", p);
+///   })
+/// \endcode
+extern const internal::VariadicDynCastAllOfMatcher
+    blockDecl;
+
 /// Matches Objective-C instance variable declarations.
 ///
 /// Example matches _enabled
@@ -3479,7 +3492,7 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
 }
 
 /// Matches the n'th parameter of a function or an ObjC method
-/// declaration.
+/// declaration or a block.
 ///
 /// Given
 /// \code
@@ -3500,7 +3513,8 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) {
 /// matching y.
 AST_POLYMORPHIC_MATCHER_P2(hasParameter,
                            AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
-                                                           ObjCMethodDecl),
+                                                           ObjCMethodDecl,
+                                                           BlockDecl),
                            unsigned, N, internal::Matcher,
                            InnerMatcher) {
   return (N < Node.parameters().size()
@@ -3561,7 +3575,8 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
   return Matched;
 }
 
-/// Matches any parameter of a function or ObjC method declaration.
+/// Matches any parameter of a function or an ObjC method declaration or a
+/// block.
 ///
 /// Does not match the 'this' parameter of a method.
 ///
@@ -3582,9 +3597,19 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam,
 /// the matcher objcMethodDecl(hasAnyParameter(hasName("y")))
 /// matches the declaration of method f with hasParameter
 /// matching y.
+///
+/// For blocks, given
+/// \code
+///   b = ^(int y) { printf("%d", y) };
+/// \endcode
+/// 
+/// the matcher blockDecl(hasAnyParameter(hasName("y")))
+/// matches the declaration of the block b with hasParameter
+/// matching y.
 AST_POLYMORPHIC_MATCHER_P(hasAnyParameter,
                           AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl,
-                                                          ObjCMethodDecl),
+                                                          ObjCMethodDecl,
+                                                          BlockDecl),
                           internal::Matcher,
                           InnerMatcher) {
   return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(),
diff --git a/lib/ASTMatchers/ASTMatchersInternal.cpp b/lib/ASTMatchers/ASTMatchersInternal.cpp
index e9ff825d90..92b680fd17 100644
--- a/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -626,6 +626,8 @@ const internal::VariadicDynCastAllOfMatcher
     objcCategoryImplDecl;
 const internal::VariadicDynCastAllOfMatcher
     objcMethodDecl;
+const internal::VariadicDynCastAllOfMatcher
+    blockDecl;
 const internal::VariadicDynCastAllOfMatcher objcIvarDecl;
 const internal::VariadicDynCastAllOfMatcher
     objcPropertyDecl;
diff --git a/lib/ASTMatchers/Dynamic/Registry.cpp b/lib/ASTMatchers/Dynamic/Registry.cpp
index e6a6a20916..84e6e450f2 100644
--- a/lib/ASTMatchers/Dynamic/Registry.cpp
+++ b/lib/ASTMatchers/Dynamic/Registry.cpp
@@ -136,6 +136,7 @@ RegistryMaps::RegistryMaps() {
   REGISTER_MATCHER(autoType);
   REGISTER_MATCHER(binaryOperator);
   REGISTER_MATCHER(binaryConditionalOperator);
+  REGISTER_MATCHER(blockDecl);
   REGISTER_MATCHER(blockPointerType);
   REGISTER_MATCHER(booleanType);
   REGISTER_MATCHER(breakStmt);
diff --git a/unittests/ASTMatchers/ASTMatchersTest.h b/unittests/ASTMatchers/ASTMatchersTest.h
index 7cfe5b9e37..504668872f 100644
--- a/unittests/ASTMatchers/ASTMatchersTest.h
+++ b/unittests/ASTMatchers/ASTMatchersTest.h
@@ -132,7 +132,7 @@ testing::AssertionResult matchesObjC(const std::string &Code, const T &AMatcher,
                                      bool ExpectMatch = true) {
   return matchesConditionally(Code, AMatcher, ExpectMatch,
                               {"-fobjc-nonfragile-abi", "-Wno-objc-root-class",
-                               "-Wno-incomplete-implementation"},
+                               "-fblocks", "-Wno-incomplete-implementation"},
                               FileContentMappings(), "input.m");
 }
 
diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
index c9c70a5f25..b18cd63130 100644
--- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
+++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp
@@ -541,6 +541,8 @@ TEST(HasParameter, CallsInnerMatcher) {
                          cxxMethodDecl(hasParameter(0, hasName("x")))));
   EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
                           objcMethodDecl(hasParameter(0, hasName("x")))));
+  EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
+                          blockDecl(hasParameter(0, hasName("p")))));
 }
 
 TEST(HasParameter, DoesNotMatchIfIndexOutOfBounds) {
@@ -572,6 +574,8 @@ TEST(HasAnyParameter, MatchesIndependentlyOfPosition) {
     cxxMethodDecl(hasAnyParameter(hasType(recordDecl(hasName("X")))))));
   EXPECT_TRUE(matchesObjC("@interface I -(void)f:(int) x; @end",
                           objcMethodDecl(hasAnyParameter(hasName("x")))));
+  EXPECT_TRUE(matchesObjC("int main() { void (^b)(int) = ^(int p) {}; }",
+                          blockDecl(hasAnyParameter(hasName("p")))));
 }
 
 TEST(Returns, MatchesReturnTypes) {