compnerd created this revision.
compnerd added a reviewer: aaron.ballman.
Herald added a project: clang.
compnerd requested review of this revision.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87532

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/SemaObjC/attr-swift_bridged_typedef.m

Index: clang/test/SemaObjC/attr-swift_bridged_typedef.m
===================================================================
--- clang/test/SemaObjC/attr-swift_bridged_typedef.m
+++ clang/test/SemaObjC/attr-swift_bridged_typedef.m
@@ -7,3 +7,30 @@
 
 struct __attribute__((swift_bridged_typedef)) S {};
 // expected-error@-1 {{'swift_bridged_typedef' attribute only applies to typedefs}}
+
+// 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
+
+__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 {};
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ 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<SwiftBridgeAttr>()) {
+    S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL.getAttrName();
+    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 @@
     break;
 
   // Swift attributes.
+  case ParsedAttr::AT_SwiftBridge:
+    handleSwiftBridge(S, D, AL);
+    break;
   case ParsedAttr::AT_SwiftBridgedTypedef:
     handleSimpleAttribute<SwiftBridgedTypedefAttr>(S, D, AL);
     break;
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -3476,6 +3476,15 @@
   }];
 }
 
+def SwiftBridgeDocs : Documentation {
+  let Category = SwiftDocs;
+  let Heading = "swift_bridge";
+  let Content = [{
+The ``swift_bridged`` attribute indicates that the type to which the attribute
+appertains is bridged to the named Swift type.
+  }];
+}
+
 def SwiftBridgedTypedefDocs : Documentation {
   let Category = SwiftDocs;
   let Heading = "swift_bridged";
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2130,6 +2130,14 @@
   let ASTNode = 0;
 }
 
+def SwiftBridge : Attr {
+  let Spellings = [GNU<"swift_bridge">];
+  let Args = [StringArgument<"SwiftType">];
+  let Subjects = SubjectList<[Tag, TypedefName, ObjCInterface, ObjCProtocol],
+                             ErrorDiag, "ExpectedType">;
+  let Documentation = [SwiftBridgeDocs];
+}
+
 def SwiftBridgedTypedef : Attr {
   let Spellings = [GNU<"swift_bridged_typedef">];
   let Subjects = SubjectList<[TypedefName], ErrorDiag, "typedefs">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to