Skip to content

Commit f80da87

Browse files
authored
[TBDGen] Add back standalone OBJC_METACLASS symbols (#70827)
It turns out there are valid usecases for exposing a standalone objc-metaclass symbols and tbd files must encode it correctly. resolves: rdar://118499886
1 parent 85437a2 commit f80da87

File tree

5 files changed

+40
-13
lines changed

5 files changed

+40
-13
lines changed

include/swift/SIL/SILSymbolVisitor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class SILSymbolVisitor {
109109
virtual void addMethodLookupFunction(ClassDecl *CD) {}
110110
virtual void addNominalTypeDescriptor(NominalTypeDecl *NTD) {}
111111
virtual void addObjCInterface(ClassDecl *CD) {}
112+
virtual void addObjCMetaclass(ClassDecl *CD) {}
112113
virtual void addObjCMethod(AbstractFunctionDecl *AFD) {}
113114
virtual void addObjCResilientClassStub(ClassDecl *CD) {}
114115
virtual void addOpaqueTypeDescriptor(OpaqueTypeDecl *OTD) {}

lib/IRGen/IRSymbolVisitor.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ class IRSymbolVisitorImpl : public SILSymbolVisitor {
162162
Visitor.addObjCInterface(CD);
163163
}
164164

165+
void addObjCMetaclass(ClassDecl *CD) override {
166+
addLinkEntity(LinkEntity::forObjCMetaclass(CD));
167+
}
168+
165169
void addObjCMethod(AbstractFunctionDecl *AFD) override {
166170
// Pass through; Obj-C methods don't have linkable symbols.
167171
Visitor.addObjCMethod(AFD);

lib/SIL/IR/SILSymbolVisitor.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,8 +333,12 @@ class SILSymbolVisitorImpl : public ASTVisitor<SILSymbolVisitorImpl> {
333333
// Metaclasses and ObjC classes (duh) are an ObjC thing, and so are not
334334
// needed in build artifacts/for classes which can't touch ObjC.
335335
if (objCCompatible) {
336-
if (isObjC || CD->getMetaclassKind() == ClassDecl::MetaclassKind::ObjC)
336+
if (isObjC)
337337
Visitor.addObjCInterface(CD);
338+
else if (CD->getMetaclassKind() == ClassDecl::MetaclassKind::ObjC)
339+
// If an ObjCInterface was not added, an external ObjC Metaclass can
340+
// still be needed for subclassing.
341+
Visitor.addObjCMetaclass(CD);
338342
else
339343
Visitor.addSwiftMetaclassStub(CD);
340344
}

test/TBD/implied_objc_symbols.swift

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,35 @@
11
// REQUIRES: VENDOR=apple
22
// RUN: %empty-directory(%t)
3+
// RUN: split-file %s %t
34

4-
// RUN: echo "import Foundation" > %t/main.swift
5-
// RUN: echo "@objc(CApi) public class Api {}" >> %t/main.swift
65
// RUN: %target-swift-frontend -emit-ir -o/dev/null -parse-as-library -module-name test -import-objc-header %S/Inputs/objc_class_header.h -validate-tbd-against-ir=missing %t/main.swift -disable-objc-attr-requires-foundation-module -emit-tbd -emit-tbd-path %t/main.tbd -tbd-install_name objc_classes
76

8-
// RUN: %validate-json %t/main.tbd | %FileCheck %s
7+
// RUN: %validate-json %t/main.tbd | %FileCheck %s --check-prefix FORMAT
8+
// RUN: %llvm-nm %t/main.tbd | %FileCheck %s --check-prefix SYMS
99

10-
// CHECK-NOT: '_OBJC_CLASS_$_CApi'
11-
// CHECK-NOT: '_OBJC_METACLASS_$_CApi'
10+
// FORMAT-NOT: '_OBJC_CLASS'
11+
// FORMAT: "objc_class"
1212

13-
// CHECK: "objc_class": [
14-
// CHECK-NEXT: "CApi"
15-
// CHECK-NEXT: ]
1613

14+
// SYMS: D _OBJC_CLASS_$_CApi
15+
// SYMS: D _OBJC_CLASS_$__TtC4test11AnotherCAPI
16+
// SYMS: D _OBJC_METACLASS_$_CApi
17+
// SYMS: D _OBJC_METACLASS_$__TtC4test11AnotherCAPI
18+
19+
/// Expect stand-alone metaclass for NotCAPIBase.
20+
// SYMS: D _OBJC_METACLASS_$__TtC4test11NotCAPIBase
21+
22+
// SYMS-NOT: _OBJC
23+
24+
25+
//--- main.swift
26+
import Foundation
27+
28+
// These declarations imply direct obj-c availability.
29+
@objc(CApi) public class Api {}
30+
public class AnotherCAPI : NSObject {}
31+
32+
public struct Empty {}
33+
// A generic one does not, however the obj-c metaclass should still be exported.
34+
public class NotCAPI<T> : AnotherCAPI {}
35+
public class NotCAPIBase : NotCAPI<Empty> {}

test/TBD/multimodule-implied-objc.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,9 @@
2323

2424
// RUN: %validate-json %t/client.tbd | %FileCheck %s
2525

26-
// CHECK: "objc_class":
27-
// CHECK: "_TtCO6client11extendedAPI6Square"
28-
// CHECK-NOT: _OBJC_CLASS_$
29-
// CHECK-NOT: _OBJC_METACLASS_$
26+
// CHECK: "_OBJC_METACLASS_$__TtCO6client11extendedAPI6Square"
27+
// CHECK-NOT: "objc_class"
28+
// CHECK-NOT: _OBJC_C
3029

3130
//--- module.modulemap
3231
module IndirectMixedDependency {

0 commit comments

Comments
 (0)