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,14 @@ let ASTNode = 0; } +def SwiftBridge : InheritableAttr { + let Spellings = [GNU<"swift_bridge">]; + let Args = [StringArgument<"SwiftType">]; + let Subjects = SubjectList<[Tag, TypedefName, ObjCInterface, ObjCProtocol], + ErrorDiag>; + let Documentation = [SwiftBridgeDocs]; +} + def SwiftBridgedTypedef : InheritableAttr { let Spellings = [GNU<"swift_bridged_typedef">]; let Subjects = SubjectList<[TypedefName], ErrorDiag>; 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,30 @@ }]; } +def SwiftBridgeDocs : Documentation { + let Category = SwiftDocs; + let Heading = "swift_bridge"; + let Content = [{ +The ``swift_bridge`` attribute indicates that the declaration to which the +attribute appertains is bridged to the named Swift type. + + .. code-block:: c + + __attribute__((__objc_root__)) + @interface Base + - (instancetype)init; + @end + + __attribute__((__swift_bridge__("BridgedI"))) + @interface I : Base + @end + +In this example, the Objective-C interface ``I`` will be made available to Swift +with the name ``BridgedI``. It would be possible for the compiler to refer to +``I`` still in order to bridge the type back to Objective-C. + }]; +} + def SwiftBridgedTypedefDocs : Documentation { let Category = SwiftDocs; let Heading = "swift_bridged"; 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 @@ -5524,6 +5524,22 @@ D->addAttr(::new (S.Context) ObjCPreciseLifetimeAttr(S.Context, AL)); } +static void handleSwiftBridge(Sema &S, Decl *D, const ParsedAttr &AL) { + // Make sure that there is a string literal as the annotation's single + // argument. + StringRef BT; + if (!S.checkStringLiteralArgumentAttr(AL, 0, BT)) + return; + + // Don't duplicate annotations that are already set. + if (D->hasAttr()) { + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + return; + } + + D->addAttr(::new (S.Context) SwiftBridgeAttr(S.Context, AL, BT)); +} + static bool isErrorParameter(Sema &S, QualType QT) { const auto *PT = QT->getAs(); if (!PT) @@ -7533,6 +7549,9 @@ break; // Swift attributes. + case ParsedAttr::AT_SwiftBridge: + handleSwiftBridge(S, D, AL); + break; case ParsedAttr::AT_SwiftBridgedTypedef: handleSimpleAttribute(S, D, AL); break; diff --git a/clang/test/AST/attr-swift_bridge.m b/clang/test/AST/attr-swift_bridge.m new file mode 100644 --- /dev/null +++ b/clang/test/AST/attr-swift_bridge.m @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -ast-dump %s | FileCheck %s + +struct __attribute__((__swift_bridge__("BridgedS"))) S; +// CHECK: RecordDecl {{.*}} struct S +// CHECK: SwiftBridgeAttr {{.*}} "BridgedS" + +struct S { +}; + +// CHECK: RecordDecl {{.*}} struct S definition +// CHECK: SwiftBridgeAttr {{.*}} Inherited "BridgedS" diff --git a/clang/test/SemaObjC/attr-swift_bridge.m b/clang/test/SemaObjC/attr-swift_bridge.m new file mode 100644 --- /dev/null +++ b/clang/test/SemaObjC/attr-swift_bridge.m @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -verify -fsyntax-only %s + +// expected-error@+1 {{'__swift_bridge__' attribute takes one argument}} +__attribute__((__swift_bridge__)) +@interface I +@end + +// expected-error@+1 {{'__swift_bridge__' attribute requires a string}} +__attribute__((__swift_bridge__(1))) +@interface J +@end + +// expected-error@+1 {{'__swift_bridge__' attribute takes one argument}} +__attribute__((__swift_bridge__("K", 1))) +@interface K +@end + +@interface L +// expected-error@+1 {{'__swift_bridge__' attribute only applies to tag types, typedefs, Objective-C interfaces, and Objective-C protocols}} +- (void)method __attribute__((__swift_bridge__("method"))); +@end + +__attribute__((__swift_bridge__("Array"))) +@interface NSArray +@end + +__attribute__((__swift_bridge__("ProtocolP"))) +@protocol P +@end + +typedef NSArray *NSArrayAlias __attribute__((__swift_bridge__("ArrayAlias"))); + +struct __attribute__((__swift_bridge__("StructT"))) T {};