diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 0b945d73f0d74d..5026d4475b38aa 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -975,6 +975,10 @@ AST Matchers - Add ``exportDecl`` matcher to match export declaration. +- Ensure ``hasType`` and ``hasDeclaration`` match Objective-C interface declarations. + +- Ensure ``pointee`` matches Objective-C pointer types. + clang-format ------------ diff --git a/clang/include/clang/ASTMatchers/ASTMatchers.h b/clang/include/clang/ASTMatchers/ASTMatchers.h index efad600a3c58cd..897aa25dc95cc1 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchers.h +++ b/clang/include/clang/ASTMatchers/ASTMatchers.h @@ -4044,7 +4044,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( AST_POLYMORPHIC_MATCHER_P_OVERLOAD( hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl, - CXXBaseSpecifier), + CXXBaseSpecifier, ObjCInterfaceDecl), internal::Matcher, InnerMatcher, 1) { QualType QT = internal::getUnderlyingType(Node); if (!QT.isNull()) @@ -7445,7 +7445,8 @@ extern const AstTypeMatcher rValueReferenceType; AST_TYPELOC_TRAVERSE_MATCHER_DECL( pointee, getPointee, AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, - PointerType, ReferenceType)); + PointerType, ReferenceType, + ObjCObjectPointerType)); /// Matches typedef types. /// diff --git a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h index ab8b146453e761..04804d5def0461 100644 --- a/clang/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/clang/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -161,6 +161,9 @@ inline QualType getUnderlyingType(const FriendDecl &Node) { inline QualType getUnderlyingType(const CXXBaseSpecifier &Node) { return Node.getType(); } +inline QualType getUnderlyingType(const ObjCInterfaceDecl &Node) { + return Node.getTypeForDecl()->getPointeeType(); +} /// Unifies obtaining a `TypeSourceInfo` from different node types. template { return matchesDecl(Node.getDecl(), Finder, Builder); } + bool matchesSpecialized(const ObjCInterfaceDecl &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getCanonicalDecl(), Finder, Builder); + } + /// Extracts the operator new of the new call and returns whether the /// inner matcher matches on it. bool matchesSpecialized(const CXXNewExpr &Node, @@ -1213,7 +1221,7 @@ using HasDeclarationSupportedTypes = ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr, QualType, RecordType, TagType, TemplateSpecializationType, TemplateTypeParmType, TypedefType, - UnresolvedUsingType, ObjCIvarRefExpr>; + UnresolvedUsingType, ObjCIvarRefExpr, ObjCInterfaceDecl>; /// A Matcher that allows binding the node it matches to an id. /// diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp index 84a7fa4d36b480..bf9dc5f2373f9e 100644 --- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp +++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp @@ -1114,7 +1114,8 @@ AST_TYPELOC_TRAVERSE_MATCHER_DEF(hasValueType, AST_TYPELOC_TRAVERSE_MATCHER_DEF( pointee, AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, - PointerType, ReferenceType)); + PointerType, ReferenceType, + ObjCObjectPointerType)); const internal::VariadicDynCastAllOfMatcher ompExecutableDirective; diff --git a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 1d18869a6b8afc..75d6ca5ba17f8b 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -283,6 +283,12 @@ TEST(HasDeclaration, HasDeclarationOfTypeAlias) { hasDeclaration(typeAliasTemplateDecl())))))))); } +TEST(HasDeclaration, HasDeclarationOfObjCInterface) { + EXPECT_TRUE(matchesObjC("@interface BaseClass @end void f() {BaseClass* b;}", + varDecl(hasType(objcObjectPointerType( + pointee(hasDeclaration(objcInterfaceDecl()))))))); +} + TEST(HasUnqualifiedDesugaredType, DesugarsUsing) { EXPECT_TRUE( matches("struct A {}; using B = A; B b;",