Skip to content

Commit fdc5aa8

Browse files
committed
Undo behavior change for final overrides
A previous change made it so that an objcImpl extension could declare a `final` or `static` member which overrode an `@objc` superclass method, or witnessed an `@objc` protocol requirement, without itself being `@objc`. Prevent that from happening by allowing processing of `final` members to continue to later codepaths, rather than returning early. Fixes rdar://136113393.
1 parent cd8d3ad commit fdc5aa8

File tree

3 files changed

+14
-5
lines changed

3 files changed

+14
-5
lines changed

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,11 +1519,9 @@ static std::optional<ObjCReason> shouldMarkAsObjC(const ValueDecl *VD,
15191519
ObjCImplementationAttr *attrToWarnOfObjCImplBehaviorChange = nullptr;
15201520

15211521
if (isMemberOfObjCImplementationExtension(VD)) {
1522-
// A `final` member of an @objc @implementation extension is not @objc.
1523-
if (VD->isFinal())
1524-
return std::nullopt;
1525-
// Other members get a special reason.
1526-
if (canInferImplicitObjC(/*allowAnyAccess*/true)) {
1522+
// A non-`final` member of an @objc @implementation extension is @objc
1523+
// with a special reason.
1524+
if (!VD->isFinal() && canInferImplicitObjC(/*allowAnyAccess*/true)) {
15271525
auto ext = VD->getDeclContext()->getAsDecl();
15281526
auto attr = ext->getAttrs()
15291527
.getAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);

test/decl/ext/objc_implementation.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,11 @@ protocol EmptySwiftProto {}
446446
// expected-error@-1 {{method cannot be in an @objc @implementation extension of a class (without final or @nonobjc) because the type of the parameter cannot be represented in Objective-C}}
447447
// expected-note@-2 {{protocol-constrained type containing protocol 'EmptySwiftProto' cannot be represented in Objective-C}}
448448
}
449+
450+
override public static func superclassClassMethod() {
451+
// rdar://136113393: `static override` could make a non-`@objc` override
452+
// of an `@objc` member when using new syntax.
453+
}
449454
}
450455

451456
// Intentionally using `@_objcImplementation` for this test; do not upgrade!

test/decl/ext/objc_implementation_early_adopter.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,12 @@ protocol EmptySwiftProto {}
446446
// expected-warning@-1 {{instance method 'privateNonObjCMethod' will become implicitly '@objc' after adopting '@objc @implementation'; add 'final' to keep the current behavior}} {{3-3=final }}
447447
// expected-note@-2 {{add '@objc' to expose this instance method to Objective-C}} {{3-3=@objc }}
448448
}
449+
450+
override public static func superclassClassMethod() {
451+
// rdar://136113393: `static override` could make a non-`@objc` override
452+
// of an `@objc` member when using new syntax. (We would get a warning here
453+
// if that bug were still in place.)
454+
}
449455
}
450456

451457
// Intentionally using `@_objcImplementation` for this test; do not upgrade!

0 commit comments

Comments
 (0)