diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -2130,6 +2130,12 @@ let ASTNode = 0; } +def SwiftObjCMembers : Attr { + let Spellings = [GNU<"swift_objc_members">]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [SwiftObjCMembersDocs]; +} + def SwiftError : InheritableAttr { let Spellings = [GNU<"swift_error">]; let Args = [ diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -3476,6 +3476,16 @@ }]; } +def SwiftObjCMembersDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_objc_members"; + let Content = [{ +This attribute indicates that Swift subclasses and members of Swift extensions +of this class will be implicitly marked with the ``@objcMembers`` Swift +attribute, exposing them back to Objective-C. + }]; +} + def SwiftErrorDocs : Documentation { let Category = SwiftDocs; let Heading = "swift_error"; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -7536,6 +7536,9 @@ case ParsedAttr::AT_SwiftError: handleSwiftError(S, D, AL); break; + case ParsedAttr::AT_SwiftObjCMembers: + handleSimpleAttribute(S, D, AL); + break; // XRay attributes. case ParsedAttr::AT_XRayLogArgs: diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -150,6 +150,7 @@ // CHECK-NEXT: SwiftError (SubjectMatchRule_function, SubjectMatchRule_objc_method) // CHECK-NEXT: SwiftErrorResult (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: SwiftIndirectResult (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: SwiftObjCMembers (SubjectMatchRule_objc_interface) // CHECK-NEXT: TLSModel (SubjectMatchRule_variable_is_thread_local) // CHECK-NEXT: Target (SubjectMatchRule_function) // CHECK-NEXT: TestTypestate (SubjectMatchRule_function_is_member) diff --git a/clang/test/SemaObjC/attr-swift_objc_members.m b/clang/test/SemaObjC/attr-swift_objc_members.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/attr-swift_objc_members.m @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +#if !__has_attribute(swift_objc_members) +#error cannot verify presence of swift_objc_members attribute +#endif + +__attribute__((__swift_objc_members__)) +__attribute__((__objc_root_class__)) +@interface I +@end + +__attribute__((swift_objc_members)) +@protocol P +@end +// expected-error@-3 {{'swift_objc_members' attribute only applies to Objective-C interfaces}} + +__attribute__((swift_objc_members)) +extern void f(void); +// expected-error@-2 {{'swift_objc_members' attribute only applies to Objective-C interfaces}} + +// expected-error@+1 {{'__swift_objc_members__' attribute takes no arguments}} +__attribute__((__swift_objc_members__("J"))) +@interface J +@end