plotfi updated this revision to Diff 451041.
plotfi added a comment.
Herald added a reviewer: aaron.ballman.
Updating implementation to use an objc_direct_visible attr to explicitly mark
when we want objc_direct to be exposed outside of the link unit.
Work on dropping the selector param has been proposed in D131424
<https://reviews.llvm.org/D131424>
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,41 @@
+// RUN: %clang -fobjc-arc -Wno-objc-root-class -ObjC -fobjc-runtime=ios -FFoundation \
+// 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: -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: -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:>"
+
+@interface C
+- (void)testMethod:(int)arg1 bar:(float)arg2 __attribute((objc_direct)) __attribute__((objc_direct_visible));
+@end
+
+#ifndef NO_OBJC_IMPL
+@implementation C
+- (void)testMethod:(int)arg1 bar:(float)arg2 __attribute((objc_direct)) __attribute__((objc_direct_visible)) {
+}
+@end
+#endif
+
+C *c;
+
+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,20 @@
}
}
+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()) {
+ 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)) {
@@ -8782,6 +8796,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
@@ -761,6 +761,8 @@
const CGFunctionInfo &FI = CGM.getTypes().arrangeObjCMethodDeclaration(OMD);
if (OMD->isDirectMethod()) {
Fn->setVisibility(llvm::Function::HiddenVisibility);
+ if (OMD->isDirectMethodVisible())
+ Fn->setVisibility(llvm::Function::DefaultVisibility);
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
@@ -5377,6 +5377,15 @@
}];
}
+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.
+ }];
+}
+
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
@@ -2248,6 +2248,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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits