Skip to content

Commit 69171ea

Browse files
committed
Set a minimum deployment target for objcImpl
We’re not committing to @objc @implementation back-deploying to pre-stable Apple platforms.
1 parent e531069 commit 69171ea

File tree

4 files changed

+36
-30
lines changed

4 files changed

+36
-30
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1796,6 +1796,10 @@ ERROR(attr_objc_implementation_no_conformance,none,
17961796
"add this conformance %select{with an ordinary extension|"
17971797
"in the Objective-C header}1",
17981798
(Type, bool))
1799+
ERROR(attr_objc_implementation_raise_minimum_deployment_target,none,
1800+
"'@implementation' of an Objective-C class requires a minimum deployment "
1801+
"target of at least %0 %1",
1802+
(StringRef, llvm::VersionTuple))
17991803

18001804
ERROR(member_of_objc_implementation_not_objc_or_final,none,
18011805
"%kind0 does not match any %kindonly0 declared in the headers for %1; "

lib/Sema/TypeCheckAttr.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,6 +1607,17 @@ visitObjCImplementationAttr(ObjCImplementationAttr *attr) {
16071607

16081608
return;
16091609
}
1610+
1611+
// While it's possible that @objc @implementation would function with
1612+
// pre-stable runtimes, this isn't a configuration that's been tested or
1613+
// supported.
1614+
auto deploymentAvailability = AvailabilityContext::forDeploymentTarget(Ctx);
1615+
if (!deploymentAvailability.isContainedIn(Ctx.getSwift50Availability())) {
1616+
diagnose(attr->getLocation(),
1617+
diag::attr_objc_implementation_raise_minimum_deployment_target,
1618+
prettyPlatformString(targetPlatform(Ctx.LangOpts)),
1619+
Ctx.getSwift50Availability().getOSVersion().getLowerEndpoint());
1620+
}
16101621
}
16111622
else if (auto AFD = dyn_cast<AbstractFunctionDecl>(D)) {
16121623
if (!hasObjCImplementationFeature(D, attr, Feature::CImplementation))

stdlib/public/runtime/Metadata.cpp

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3980,36 +3980,10 @@ swift::swift_updatePureObjCClassMetadata(Class cls,
39803980
ClassLayoutFlags flags,
39813981
size_t numFields,
39823982
const TypeLayout * const *fieldTypes) {
3983-
auto self = (ObjCClass *)cls;
3984-
bool requiresUpdate = SWIFT_RUNTIME_WEAK_CHECK(_objc_realizeClassFromSwift);
3985-
3986-
// Realize the superclass first.
3987-
(void)swift_getInitializedObjCClass((Class)self->Isa);
3988-
3989-
auto rodata = getROData(self);
3990-
3991-
// If we're running on a older Objective-C runtime, just realize
3992-
// the class.
3993-
if (!requiresUpdate) {
3994-
// If we don't have a backward deployment layout, we cannot proceed here.
3995-
if (rodata->InstanceSize == 0) {
3996-
fatalError(0, "class %s does not have a fragile layout; "
3997-
"the deployment target was newer than this OS\n",
3998-
rodata->Name);
3999-
}
4000-
4001-
// Realize the class. This causes the runtime to slide the field offsets
4002-
// stored in the field offset globals.
4003-
//
4004-
// Note that the field offset vector is *not* updated; however in
4005-
// Objective-C interop mode, we don't actually use the field offset vector
4006-
// of non-generic classes.
4007-
//
4008-
// In particular, class mirrors always use the Objective-C ivar descriptors,
4009-
// which point at field offset globals and not the field offset vector.
4010-
swift_getInitializedObjCClass((Class)self);
4011-
return cls;
4012-
}
3983+
bool hasRealizeClassFromSwift =
3984+
SWIFT_RUNTIME_WEAK_CHECK(_objc_realizeClassFromSwift);
3985+
assert(hasRealizeClassFromSwift);
3986+
(void)hasRealizeClassFromSwift;
40133987

40143988
SWIFT_DEFER {
40153989
// Realize the class. This causes the runtime to slide the field offsets
@@ -4019,7 +3993,10 @@ swift::swift_updatePureObjCClassMetadata(Class cls,
40193993

40203994
// Update the field offset globals using runtime type information; the layout
40213995
// of resilient types might be different than the statically-emitted layout.
3996+
ObjCClass *self = (ObjCClass *)cls;
3997+
ClassROData *rodata = getROData(self);
40223998
ClassIvarList *ivars = rodata->IvarList;
3999+
40234000
if (!ivars) {
40244001
assert(numFields == 0);
40254002
return cls;
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Hardcode x86_64 macOS because Apple Silicon was born ABI-stable
2+
// RUN: %target-typecheck-verify-swift -import-objc-header %S/Inputs/objc_implementation.h -target x86_64-apple-macosx10.14.3
3+
// REQUIRES: objc_interop
4+
// REQUIRES: OS=macosx
5+
6+
@_objcImplementation extension ObjCImplSubclass {
7+
// expected-error@-1 {{'@implementation' of an Objective-C class requires a minimum deployment target of at least macOS 10.14.4}}
8+
}
9+
10+
@_objcImplementation(Conformance) extension ObjCClass {
11+
// no-error@-1
12+
func requiredMethod1() {}
13+
func requiredMethod2() {}
14+
}

0 commit comments

Comments
 (0)