Index: docs/LibASTMatchersReference.html =================================================================== --- docs/LibASTMatchersReference.html +++ docs/LibASTMatchersReference.html @@ -337,6 +337,15 @@ +
Matches Objective-C category declarations. + +Example matches Foo (Additions) + @interface Foo (Additions) + @end +
Matches Objective-C interface declarations. @@ -346,6 +355,50 @@
Matches Objective-C instance variable declarations.
+
+Example matches _enabled
+ @implementation Foo {
+ BOOL _enabled;
+ }
+ @end
+Matches Objective-C method declarations.
+
+Example matches both declaration and definition of -[Foo method]
+ @interface Foo
+ - (void)method;
+ @end
+
+ @implementation Foo
+ - (void)method {}
+ @end
+Matches Objective-C property declarations. + +Example matches enabled + @interface Foo + @property BOOL enabled; + @end +
Matches Objective-C protocol declarations. + +Example matches FooDelegate + @protocol FooDelegate + @end +
Matches parameter variable declarations.
Index: include/clang/ASTMatchers/ASTMatchers.h
===================================================================
--- include/clang/ASTMatchers/ASTMatchers.h
+++ include/clang/ASTMatchers/ASTMatchers.h
@@ -1118,6 +1118,69 @@
Decl,
ObjCInterfaceDecl> objcInterfaceDecl;
+/// \brief Matches Objective-C protocol declarations.
+///
+/// Example matches FooDelegate
+/// \code
+/// @protocol FooDelegate
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCProtocolDecl> objcProtocolDecl;
+
+/// \brief Matches Objective-C category declarations.
+///
+/// Example matches Foo (Additions)
+/// \code
+/// @interface Foo (Additions)
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCCategoryDecl> objcCategoryDecl;
+
+/// \brief Matches Objective-C method declarations.
+///
+/// Example matches both declaration and definition of -[Foo method]
+/// \code
+/// @interface Foo
+/// - (void)method;
+/// @end
+///
+/// @implementation Foo
+/// - (void)method {}
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCMethodDecl> objcMethodDecl;
+
+/// \brief Matches Objective-C instance variable declarations.
+///
+/// Example matches _enabled
+/// \code
+/// @implementation Foo {
+/// BOOL _enabled;
+/// }
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCIvarDecl> objcIvarDecl;
+
+/// \brief Matches Objective-C property declarations.
+///
+/// Example matches enabled
+/// \code
+/// @interface Foo
+/// @property BOOL enabled;
+/// @end
+/// \endcode
+const internal::VariadicDynCastAllOfMatcher<
+ Decl,
+ ObjCPropertyDecl> objcPropertyDecl;
+
/// \brief Matches expressions that introduce cleanups to be run at the end
/// of the sub-expression's evaluation.
///
Index: lib/ASTMatchers/Dynamic/Registry.cpp
===================================================================
--- lib/ASTMatchers/Dynamic/Registry.cpp
+++ lib/ASTMatchers/Dynamic/Registry.cpp
@@ -360,6 +360,11 @@
REGISTER_MATCHER(numSelectorArgs);
REGISTER_MATCHER(ofClass);
REGISTER_MATCHER(objcInterfaceDecl);
+ REGISTER_MATCHER(objcProtocolDecl);
+ REGISTER_MATCHER(objcCategoryDecl);
+ REGISTER_MATCHER(objcMethodDecl);
+ REGISTER_MATCHER(objcIvarDecl);
+ REGISTER_MATCHER(objcPropertyDecl);
REGISTER_MATCHER(objcMessageExpr);
REGISTER_MATCHER(objcObjectPointerType);
REGISTER_MATCHER(on);
Index: unittests/ASTMatchers/ASTMatchersNodeTest.cpp
===================================================================
--- unittests/ASTMatchers/ASTMatchersNodeTest.cpp
+++ unittests/ASTMatchers/ASTMatchersNodeTest.cpp
@@ -1500,9 +1500,10 @@
std::string Objc1String =
"@interface Str "
- " - (Str *)uppercaseString:(Str *)str;"
+ " - (Str *)uppercaseString;"
"@end "
"@interface foo "
+ "- (void)contents;"
"- (void)meth:(Str *)text;"
"@end "
" "
@@ -1540,5 +1541,45 @@
)));
}
+TEST(ObjCDeclMacher, CoreDecls) {
+ std::string ObjCString =
+ "@protocol Proto "
+ "- (void)protoDidThing; "
+ "@end "
+ "@interface Thing "
+ "@property int enabled; "
+ "@end "
+ "@interface Thing (ABC) "
+ "- (void)abc_doThing; "
+ "@end "
+ "@implementation Thing "
+ "{ id _ivar; } "
+ "- (void)anything {} "
+ "@end "
+ ;
+
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcProtocolDecl(hasName("Proto"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcCategoryDecl(hasName("ABC"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcMethodDecl(hasName("protoDidThing"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcMethodDecl(hasName("abc_doThing"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcMethodDecl(hasName("anything"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcIvarDecl(hasName("_ivar"))));
+ EXPECT_TRUE(matchesObjC(
+ ObjCString,
+ objcPropertyDecl(hasName("enabled"))));
+}
+
} // namespace ast_matchers
} // namespace clang
Index: unittests/ASTMatchers/ASTMatchersTest.h
===================================================================
--- unittests/ASTMatchers/ASTMatchersTest.h
+++ unittests/ASTMatchers/ASTMatchersTest.h
@@ -61,7 +61,7 @@
template
testing::AssertionResult matchesConditionally(
const std::string &Code, const T &AMatcher, bool ExpectMatch,
- llvm::StringRef CompileArg,
+ std::vector Args,
const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
const std::string &Filename = "input.cc") {
bool Found = false, DynamicFound = false;
@@ -81,8 +81,8 @@
// FIXME: This is a hack to work around the fact that there's no way to do the
// equivalent of runToolOnCodeWithArgs without instantiating a full Driver.
// We should consider having a function, at least for tests, that invokes cc1.
- std::vector Args = {CompileArg, "-frtti", "-fexceptions",
- "-target", "i386-unknown-unknown"};
+ Args.insert(Args.end(), {"-frtti", "-fexceptions",
+ "-target", "i386-unknown-unknown"});
if (!runToolOnCodeWithArgs(
Factory->create(), Code, Args, Filename, "clang-tool",
std::make_shared(), VirtualMappedFiles)) {
@@ -105,6 +105,17 @@
}
template
+testing::AssertionResult matchesConditionally(
+ const std::string &Code, const T &AMatcher, bool ExpectMatch,
+ llvm::StringRef CompileArg,
+ const FileContentMappings &VirtualMappedFiles = FileContentMappings(),
+ const std::string &Filename = "input.cc") {
+ return matchesConditionally(
+ Code, AMatcher, ExpectMatch, std::vector{CompileArg},
+ VirtualMappedFiles, Filename);
+}
+
+template
testing::AssertionResult matches(const std::string &Code, const T &AMatcher) {
return matchesConditionally(Code, AMatcher, true, "-std=c++11");
}
@@ -117,10 +128,13 @@
template
testing::AssertionResult matchesObjC(const std::string &Code,
- const T &AMatcher) {
+ const T &AMatcher,
+ bool ExpectMatch = true) {
return matchesConditionally(
- Code, AMatcher, true,
- "", FileContentMappings(), "input.m");
+ Code, AMatcher, ExpectMatch,
+ {"-fobjc-nonfragile-abi",
+ "-Wno-objc-root-class", "-Wno-incomplete-implementation"},
+ FileContentMappings(), "input.m");
}
template
@@ -145,10 +159,8 @@
template
testing::AssertionResult notMatchesObjC(const std::string &Code,
- const T &AMatcher) {
- return matchesConditionally(
- Code, AMatcher, false,
- "", FileContentMappings(), "input.m");
+ const T &AMatcher) {
+ return matchesObjC(Code, AMatcher, false);
}