stephanemoore created this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits. stephanemoore added a reviewer: aaron.ballman.
This change adds a new AST matcher to detect Objective-C classes that are subclasses of matching Objective-C interfaces. Test Notes: Ran clang unit tests. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D60543 Files: clang/docs/LibASTMatchersReference.html clang/include/clang/ASTMatchers/ASTMatchers.h clang/lib/ASTMatchers/Dynamic/Registry.cpp clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
Index: clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp =================================================================== --- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp +++ clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp @@ -1389,6 +1389,23 @@ EXPECT_TRUE(matchesObjC("void f() { ^{}(); }", blockExpr())); } +TEST(IsSubclassOfInterfaceMatcher, SubclassMatching) { + std::string ObjCString = "@interface A @end" + "@interface B : A @end" + "@interface C : B @end"; + EXPECT_TRUE(matchesObjC( + ObjCString, objcInterfaceDecl(isSubclassOfInterface(hasName("A"))))); + EXPECT_TRUE(matchesObjC(ObjCString, + objcInterfaceDecl(isSubclassOfInterface(hasName("A")), + unless(hasName("B"))))); + EXPECT_TRUE(matchesObjC( + ObjCString, objcInterfaceDecl(isSubclassOfInterface(hasName("B"))))); + EXPECT_FALSE(matchesObjC( + ObjCString, objcInterfaceDecl(isSubclassOfInterface(hasName("C"))))); + EXPECT_FALSE(matchesObjC( + ObjCString, objcInterfaceDecl(isSubclassOfInterface(hasName("X"))))); +} + TEST(StatementCountIs, FindsNoStatementsInAnEmptyCompoundStatement) { EXPECT_TRUE(matches("void f() { }", compoundStmt(statementCountIs(0)))); Index: clang/lib/ASTMatchers/Dynamic/Registry.cpp =================================================================== --- clang/lib/ASTMatchers/Dynamic/Registry.cpp +++ clang/lib/ASTMatchers/Dynamic/Registry.cpp @@ -393,6 +393,7 @@ REGISTER_MATCHER(isStaticLocal); REGISTER_MATCHER(isStaticStorageClass); REGISTER_MATCHER(isStruct); + REGISTER_MATCHER(isSubclassOfInterface); REGISTER_MATCHER(isTemplateInstantiation); REGISTER_MATCHER(isTypeDependent); REGISTER_MATCHER(isUnion); Index: clang/include/clang/ASTMatchers/ASTMatchers.h =================================================================== --- clang/include/clang/ASTMatchers/ASTMatchers.h +++ clang/include/clang/ASTMatchers/ASTMatchers.h @@ -1461,6 +1461,35 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> objcFinallyStmt; +/// Matches Objective-C classes that directly or indirectly subclass +/// a matching superclass. +/// +/// Note that a class is not considered to be a subclass of itself. +/// +/// Example matches implementation declarations for Y and Z. +/// (matcher = objcInterfaceDecl(isSubclassOfInterface(hasName("X")))) +/// \code +/// @interface X +/// @end +/// @interface Y : X // directly derived +/// @end +/// @interface Z : Y // indirectly derived +/// @end +/// \endcode +AST_MATCHER_P(ObjCInterfaceDecl, isSubclassOfInterface, + internal::Matcher<ObjCInterfaceDecl>, + InnerMatcher) { + // Check if any of the superclasses of the class match. + for (const ObjCInterfaceDecl *SuperClass = Node.getSuperClass(); + SuperClass != nullptr; SuperClass = SuperClass->getSuperClass()) { + if (InnerMatcher.matches(*SuperClass, Finder, Builder)) + return true; + } + + // No matches found. + return false; +} + /// Matches expressions that introduce cleanups to be run at the end /// of the sub-expression's evaluation. /// Index: clang/docs/LibASTMatchersReference.html =================================================================== --- clang/docs/LibASTMatchersReference.html +++ clang/docs/LibASTMatchersReference.html @@ -6285,6 +6285,23 @@ </pre></td></tr> +<tr><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>></td><td class="name" onclick="toggle('isSubclassOfInterface0')"><a name="isSubclassOfInterface0Anchor">isSubclassOfInterface</a></td><td>Matcher<<a href="https://clang.llvm.org/doxygen/classclang_1_1ObjCInterfaceDecl.html">ObjCInterfaceDecl</a>> InnerMatcher</td></tr> +<tr><td colspan="4" class="doc" id="isSubclassOfInterface0"><pre>Matches Objective-C classes that directly or indirectly subclass +a matching superclass. + +Note that a class is not considered to be a subclass of itself. + +Example matches implementation declarations for Y and Z. + (matcher = objcInterfaceDecl(isSubclassOfInterface(hasName("X")))) + @interface X + @end + @interface Y : X // directly derived + @end + @interface Z : Y // indirectly derived + @end +</pre></td></tr> + + <tr><td>Matcher<<a href="https://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="https://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.
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits