Skip to content

Commit 1743235

Browse files
authored
Merge pull request #24704 from slavapestov/always-emit-class-stubs
Always emit class stubs
2 parents ce3290a + 12469f5 commit 1743235

File tree

4 files changed

+36
-33
lines changed

4 files changed

+36
-33
lines changed

lib/IRGen/GenClass.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,6 @@ namespace {
12111211
// hierarchy crosses resilience domains, we use a
12121212
// slightly different query here.
12131213
if (theClass->checkAncestry(AncestryFlags::ResilientOther)) {
1214-
assert(IGM.Context.LangOpts.EnableObjCResilientClassStubs);
12151214
return IGM.getAddrOfObjCResilientClassStub(theClass, NotForDefinition,
12161215
TypeMetadataAddress::AddressPoint);
12171216
}
@@ -2072,9 +2071,7 @@ static llvm::Function *emitObjCMetadataUpdateFunction(IRGenModule &IGM,
20722071
/// does not have statically-emitted metadata.
20732072
bool irgen::hasObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {
20742073
assert(IGM.getClassMetadataStrategy(D) == ClassMetadataStrategy::Resilient);
2075-
return (!D->isGenericContext() &&
2076-
IGM.ObjCInterop &&
2077-
IGM.Context.LangOpts.EnableObjCResilientClassStubs);
2074+
return IGM.ObjCInterop && !D->isGenericContext();
20782075
}
20792076

20802077
void irgen::emitObjCResilientClassStub(IRGenModule &IGM, ClassDecl *D) {

lib/TBDGen/TBDGen.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,16 @@ void TBDGenVisitor::visitClassDecl(ClassDecl *CD) {
379379

380380
visitNominalTypeDecl(CD);
381381

382+
bool resilientAncestry = CD->checkAncestry(AncestryFlags::ResilientOther);
383+
382384
// Types with resilient superclasses have some extra symbols.
383-
if (CD->checkAncestry(AncestryFlags::ResilientOther) ||
384-
CD->hasResilientMetadata()) {
385+
if (resilientAncestry || CD->hasResilientMetadata()) {
385386
addSymbol(LinkEntity::forClassMetadataBaseOffset(CD));
387+
}
386388

387-
auto &Ctx = CD->getASTContext();
388-
if (Ctx.LangOpts.EnableObjCResilientClassStubs) {
389+
auto &Ctx = CD->getASTContext();
390+
if (Ctx.LangOpts.EnableObjCInterop) {
391+
if (resilientAncestry) {
389392
addSymbol(LinkEntity::forObjCResilientClassStub(
390393
CD, TypeMetadataAddress::AddressPoint));
391394
}

stdlib/public/runtime/Metadata.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2711,16 +2711,23 @@ _swift_initClassMetadataImpl(ClassMetadata *self,
27112711
// globals. Note that the field offset vector is *not* updated;
27122712
// however we should not be using it for anything in a non-generic
27132713
// class.
2714-
if (auto *stub = description->getObjCResilientClassStub()) {
2715-
if (_objc_realizeClassFromSwift == nullptr ||
2716-
objc_loadClassref == nullptr) {
2717-
fatalError(0, "class %s requires missing Objective-C runtime feature; "
2718-
"the deployment target was newer than this OS\n",
2719-
self->getDescription()->Name.get());
2720-
}
2714+
auto *stub = description->getObjCResilientClassStub();
2715+
2716+
// On a new enough runtime, register the class as a replacement for
2717+
// its stub if we have one, which attaches any categories referencing
2718+
// the stub.
2719+
//
2720+
// On older runtimes, just register the class via the usual mechanism.
2721+
// The compiler enforces that @objc methods in extensions of classes
2722+
// with resilient ancestry have the correct availability, so it should
2723+
// be safe to ignore the stub in this case.
2724+
if (stub != nullptr &&
2725+
objc_loadClassref != nullptr &&
2726+
_objc_realizeClassFromSwift != nullptr) {
27212727
_objc_realizeClassFromSwift((Class) self, const_cast<void *>(stub));
2722-
} else
2728+
} else {
27232729
swift_instantiateObjCClass(self);
2730+
}
27242731
}
27252732
#else
27262733
assert(!description->hasObjCResilientClassStub());

test/Interpreter/objc_class_resilience_stubs.swift

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_struct)) -enable-library-evolution %S/../Inputs/resilient_struct.swift -emit-module -emit-module-path %t/resilient_struct.swiftmodule
44
// RUN: %target-codesign %t/%target-library-name(resilient_struct)
55

6-
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -I %t -L %t -lresilient_struct -enable-library-evolution %S/../Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule -Xfrontend -enable-resilient-objc-class-stubs
6+
// RUN: %target-build-swift-dylib(%t/%target-library-name(resilient_objc_class)) -I %t -L %t -lresilient_struct -enable-library-evolution %S/../Inputs/resilient_objc_class.swift -emit-module -emit-module-path %t/resilient_objc_class.swiftmodule
77
// RUN: %target-codesign %t/%target-library-name(resilient_objc_class)
88

99
// RUN: %target-build-swift %s -L %t -I %t -lresilient_struct -lresilient_objc_class -o %t/main %target-rpath(%t) -Xfrontend -enable-resilient-objc-class-stubs
@@ -28,6 +28,18 @@ var ResilientClassTestSuite = TestSuite("ResilientClass")
2828

2929
class ResilientNSObjectSubclass : ResilientNSObjectOutsideParent {}
3030

31+
@_optimize(none) func blackHole<T>(_: T) {}
32+
33+
@_optimize(none) func forceMetadata() {
34+
blackHole(ResilientNSObjectSubclass())
35+
}
36+
37+
// This should not crash on older runtimes because we check before
38+
// attempting to register the class stub.
39+
ResilientClassTestSuite.test("RealizeResilientClass") {
40+
forceMetadata()
41+
}
42+
3143
@objc protocol MyProtocol {
3244
func myMethod() -> Int
3345
}
@@ -61,20 +73,4 @@ ResilientClassTestSuite.test("category on other class")
6173
expectEqual(69, (o as AnotherProtocol).anotherMethod())
6274
}
6375

64-
@_optimize(none) func blackHole<T>(_: T) {}
65-
66-
@_optimize(none) func forceMetadata() {
67-
blackHole(ResilientNSObjectSubclass())
68-
}
69-
70-
if loadClassrefMissing {
71-
ResilientClassTestSuite.test("RealizeResilientClass")
72-
.crashOutputMatches("class ResilientNSObjectSubclass requires missing Objective-C runtime feature")
73-
.code {
74-
expectCrashLater()
75-
print("About to crash...")
76-
forceMetadata()
77-
}
78-
}
79-
8076
runAllTests()

0 commit comments

Comments
 (0)