plotfi updated this revision to Diff 459257.
plotfi added a comment.

Updated with some of @mwyman's feedback.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D86049/new/

https://reviews.llvm.org/D86049

Files:
  clang/include/clang/AST/DeclObjC.h
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/AST/DeclObjC.cpp
  clang/lib/CodeGen/CGObjC.cpp
  clang/lib/CodeGen/CGObjCMac.cpp
  clang/lib/Sema/SemaDeclAttr.cpp
  clang/test/CodeGenObjC/objc-direct-wrapper.m

Index: clang/test/CodeGenObjC/objc-direct-wrapper.m
===================================================================
--- /dev/null
+++ clang/test/CodeGenObjC/objc-direct-wrapper.m
@@ -0,0 +1,50 @@
+// RUN: %clang -fobjc-arc -Wno-objc-root-class -ObjC -fobjc-runtime=ios -FFoundation \
+// RUN: -DENABLE_VISIBLE_OBJC_DIRECT=1 \
+// RUN: -target x86_64-apple-macosx10.15.0 -c -o - %s | \
+// RUN: llvm-nm - | FileCheck -check-prefix=CHECK-WRAPPER %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation -c -o - %s | llvm-nm - | \
+// RUN: FileCheck -check-prefix=CHECK-DEFAULT %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class \
+// RUN: -DENABLE_VISIBLE_OBJC_DIRECT=1 \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation -c -o - %s -S -emit-llvm | \
+// RUN: FileCheck -check-prefix=CHECK-WRAPPER-IR-DEFINE %s
+
+// RUN: %clang -fobjc-arc -Wno-objc-root-class -DNO_OBJC_IMPL \
+// RUN: -DENABLE_VISIBLE_OBJC_DIRECT=1 \
+// RUN: -target x86_64-apple-macosx10.15.0 \
+// RUN: -ObjC -fobjc-runtime=ios -FFoundation -c -o - %s -S -emit-llvm | \
+// RUN: FileCheck -check-prefix=CHECK-WRAPPER-IR-DECLARE %s
+
+// CHECK-WRAPPER: T _-<C testMethod:bar:>
+         // TODO: Fix this
+// CHECK-DEFAULT: t -[C testMethod:bar:]
+// CHECK-WRAPPER-IR-DEFINE: define {{(dso_local )?}}void @"-<C testMethod:bar:>"
+// CHECK-WRAPPER-IR-DECLARE: declare {{(dso_local )?}}void @"-<C testMethod:bar:>"
+
+#if ENABLE_VISIBLE_OBJC_DIRECT
+#define OBJC_DIRECT __attribute((objc_direct)) __attribute__((objc_direct_visible))
+#else
+#define OBJC_DIRECT
+#endif
+
+@interface C
+- (void)testMethod:(int)arg1 bar:(float)arg2 OBJC_DIRECT __attribute__((visibility("default"))) ;
+@end
+
+#ifndef NO_OBJC_IMPL
+@implementation C
+- (void)testMethod:(int)arg1 bar:(float)arg2 OBJC_DIRECT {
+}
+@end
+#endif
+
+C *c;
+
+__attribute__((visibility("hidden"))) void f() {
+  [c testMethod:1 bar:1.0];
+}
Index: clang/lib/Sema/SemaDeclAttr.cpp
===================================================================
--- clang/lib/Sema/SemaDeclAttr.cpp
+++ clang/lib/Sema/SemaDeclAttr.cpp
@@ -2943,6 +2943,22 @@
   }
 }
 
+static void handleObjCDirectVisibleAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
+  // objc_direct cannot be set on methods declared in the context of a protocol
+  if (isa<ObjCProtocolDecl>(D->getDeclContext())) {
+    S.Diag(AL.getLoc(), diag::err_objc_direct_on_protocol) << false;
+    return;
+  }
+
+  if (S.getLangOpts().ObjCRuntime.allowsDirectDispatch()) {
+    if (!D->hasAttr<ObjCDirectAttr>())
+      handleSimpleAttribute<ObjCDirectAttr>(S, D, AL);
+    handleSimpleAttribute<ObjCDirectVisibleAttr>(S, D, AL);
+  } else {
+    S.Diag(AL.getLoc(), diag::warn_objc_direct_ignored) << AL;
+  }
+}
+
 static void handleObjCMethodFamilyAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
   const auto *M = cast<ObjCMethodDecl>(D);
   if (!AL.isArgIdent(0)) {
@@ -8783,6 +8799,9 @@
   case ParsedAttr::AT_ObjCDirect:
     handleObjCDirectAttr(S, D, AL);
     break;
+  case ParsedAttr::AT_ObjCDirectVisible:
+    handleObjCDirectVisibleAttr(S, D, AL);
+    break;
   case ParsedAttr::AT_ObjCDirectMembers:
     handleObjCDirectMembersAttr(S, D, AL);
     handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
Index: clang/lib/CodeGen/CGObjCMac.cpp
===================================================================
--- clang/lib/CodeGen/CGObjCMac.cpp
+++ clang/lib/CodeGen/CGObjCMac.cpp
@@ -4021,6 +4021,20 @@
     DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
   }
 
+  // If we want to explicitly export objc_direct methods, we need a name fixup.
+  if (OMD->isDirectMethodVisible() && Fn->getName().str()[0] == '\1') {
+    // Drop '\1' to work with dlsym.
+    std::string Name = Fn->getName().str().substr(1);
+
+    assert(Name[0] == '-' || Name[0] == '+');
+    assert(Name[1] == '[' && Name[Name.length() - 1] == ']');
+
+    // replace "[ ]" by  "< >" to avoid strip by ld64.
+    Name = Name.substr(0, 1) + "<" + Name.substr(2, Name.length() - 3) + ">";
+
+    Fn->setName(Name);
+  }
+
   return Fn;
 }
 
Index: clang/lib/CodeGen/CGObjC.cpp
===================================================================
--- clang/lib/CodeGen/CGObjC.cpp
+++ clang/lib/CodeGen/CGObjC.cpp
@@ -760,7 +760,9 @@
 
   const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD);
   if (OMD->isDirectMethod()) {
-    Fn->setVisibility(llvm::Function::HiddenVisibility);
+    Fn->setVisibility(OMD->isDirectMethodVisible()
+                          ? llvm::Function::DefaultVisibility
+                          : llvm::Function::HiddenVisibility);
     CGM.SetLLVMFunctionAttributes(OMD, FI, Fn, /*IsThunk=*/false);
     CGM.SetLLVMFunctionAttributesForDefinition(OMD, Fn);
   } else {
Index: clang/lib/AST/DeclObjC.cpp
===================================================================
--- clang/lib/AST/DeclObjC.cpp
+++ clang/lib/AST/DeclObjC.cpp
@@ -838,6 +838,10 @@
          !getASTContext().getLangOpts().ObjCDisableDirectMethodsForTesting;
 }
 
+bool ObjCMethodDecl::isDirectMethodVisible() const {
+  return isDirectMethod() && hasAttr<ObjCDirectVisibleAttr>();
+}
+
 bool ObjCMethodDecl::isThisDeclarationADesignatedInitializer() const {
   return getMethodFamily() == OMF_init &&
       hasAttr<ObjCDesignatedInitializerAttr>();
Index: clang/include/clang/Basic/AttrDocs.td
===================================================================
--- clang/include/clang/Basic/AttrDocs.td
+++ clang/include/clang/Basic/AttrDocs.td
@@ -5406,6 +5406,19 @@
   }];
 }
 
+def ObjCDirectVisibleDocs : Documentation {
+    let Category = DocCatDecl;
+    let Content = [{
+This attribute specifies that the ``objc_direct`` method it is placed on is to
+be vislble (ie skip marking for hidden linkage) so that it can be called across
+link unit boundaries. If the ``objc_direct`` attribute is not set manually this
+also enables the attribute (since it would not makesense to do otherwise). When
+an ObjC method is marked visible its internal name is scrubed of characters that
+cause problems with linkage or do not conform to ABI
+(ie ``\0-[a: ]`` becomes ``-<a: >``).
+    }];
+}
+
 def ObjCNonRuntimeProtocolDocs : Documentation {
   let Category = DocCatDecl;
   let Content = [{
Index: clang/include/clang/Basic/Attr.td
===================================================================
--- clang/include/clang/Basic/Attr.td
+++ clang/include/clang/Basic/Attr.td
@@ -2262,6 +2262,13 @@
   let Documentation = [ObjCDirectMembersDocs];
 }
 
+def ObjCDirectVisible : Attr {
+  let Spellings = [Clang<"objc_direct_visible">];
+  let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+  let LangOpts = [ObjC];
+  let Documentation = [ObjCDirectVisibleDocs];
+}
+
 def ObjCNonRuntimeProtocol : Attr {
   let Spellings = [Clang<"objc_non_runtime_protocol">];
   let Subjects = SubjectList<[ObjCProtocol], ErrorDiag>;
Index: clang/include/clang/AST/DeclObjC.h
===================================================================
--- clang/include/clang/AST/DeclObjC.h
+++ clang/include/clang/AST/DeclObjC.h
@@ -487,6 +487,9 @@
   /// True if the method is tagged as objc_direct
   bool isDirectMethod() const;
 
+  /// True if the method is tagged as objc_direct and objc_direct_visible
+  bool isDirectMethodVisible() const;
+
   /// True if the method has a parameter that's destroyed in the callee.
   bool hasParamDestroyedInCallee() const;
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to