[clang] 77a01d9 - Sema: add support for `__attribute__((__swift_bridge__))`

Saleem Abdulrasool via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 16 10:55:59 PDT 2020


Author: Saleem Abdulrasool
Date: 2020-09-16T17:54:57Z
New Revision: 77a01d9498a79d2e6e3f366fdb363928f188ec11

URL: https://github.com/llvm/llvm-project/commit/77a01d9498a79d2e6e3f366fdb363928f188ec11
DIFF: https://github.com/llvm/llvm-project/commit/77a01d9498a79d2e6e3f366fdb363928f188ec11.diff

LOG: Sema: add support for `__attribute__((__swift_bridge__))`

This extends semantic analysis of attributes for Swift interoperability
by introducing the `swift_bridge` attribute.  This attribute enables
bridging Objective-C types to Swift specific types.

This is based on the work of the original changes in
https://github.com/llvm/llvm-project-staging/commit/8afaf3aad2af43cfedca7a24cd817848c4e95c0c

Differential Revision: https://reviews.llvm.org/D87532
Reviewed By: Aaron Ballman

Added: 
    clang/test/AST/attr-swift_bridge.m
    clang/test/SemaObjC/attr-swift_bridge.m

Modified: 
    clang/include/clang/Basic/Attr.td
    clang/include/clang/Basic/AttrDocs.td
    clang/lib/Sema/SemaDeclAttr.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 6df348618260..adef5b6a4495 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -2130,6 +2130,14 @@ def Regparm : TypeAttr {
   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
index 7aff443e9a12..8706a3f4578c 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -3476,6 +3476,30 @@ Swift.
   }];
 }
 
+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
index 02ffd752233d..5efc989db576 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -5524,6 +5524,22 @@ static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
   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<SwiftBridgeAttr>()) {
+    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<PointerType>();
   if (!PT)
@@ -7533,6 +7549,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
     break;
 
   // Swift attributes.
+  case ParsedAttr::AT_SwiftBridge:
+    handleSwiftBridge(S, D, AL);
+    break;
   case ParsedAttr::AT_SwiftBridgedTypedef:
     handleSimpleAttribute<SwiftBridgedTypedefAttr>(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
index 000000000000..2caa86bef4c0
--- /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
index 000000000000..1c8259a6a2e7
--- /dev/null
+++ b/clang/test/SemaObjC/attr-swift_bridge.m
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -verify -fsyntax-only %s
+
+// expected-error at +1 {{'__swift_bridge__' attribute takes one argument}}
+__attribute__((__swift_bridge__))
+ at interface I
+ at end
+
+// expected-error at +1 {{'__swift_bridge__' attribute requires a string}}
+__attribute__((__swift_bridge__(1)))
+ at interface J
+ at end
+
+// expected-error at +1 {{'__swift_bridge__' attribute takes one argument}}
+__attribute__((__swift_bridge__("K", 1)))
+ at interface K
+ at end
+
+ at interface L
+// expected-error at +1 {{'__swift_bridge__' attribute only applies to tag types, typedefs, Objective-C interfaces, and Objective-C protocols}}
+- (void)method __attribute__((__swift_bridge__("method")));
+ at end
+
+__attribute__((__swift_bridge__("Array")))
+ at interface NSArray
+ at end
+
+__attribute__((__swift_bridge__("ProtocolP")))
+ at protocol P
+ at end
+
+typedef NSArray *NSArrayAlias __attribute__((__swift_bridge__("ArrayAlias")));
+
+struct __attribute__((__swift_bridge__("StructT"))) T {};


        


More information about the cfe-commits mailing list