Skip to content

Commit b69e416

Browse files
committed
Support overrides of unavailable inits in objcImpl
Suppose a superclass declares an initializer unavailable and then a subclass wants to redeclare and use it. Formally, the subclass declaration overrides the superclass one; however, Swift will not actually require the subclass to use the `override` keyword. As currently implemented, this means that the requirement will be skipped as an override, but the candidate will be included as a member implementation. Result: a “candidate does not match any requirement” diagnostic. Fix this by skipping requirements that are overrides *only* if the declaration they override is not unavailable. Fixes rdar://109541045.
1 parent 3180b16 commit b69e416

File tree

3 files changed

+24
-4
lines changed

3 files changed

+24
-4
lines changed

lib/Sema/TypeCheckDeclObjC.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2948,14 +2948,21 @@ class ObjCImplementationChecker {
29482948
void addRequirements(IterableDeclContext *idc) {
29492949
assert(idc->getDecl()->hasClangNode());
29502950
for (Decl *_member : idc->getMembers()) {
2951-
// Skip accessors; we'll match their storage instead. Also skip overrides;
2952-
// the override checker handles those.
2951+
// Skip accessors; we'll match their storage instead.
29532952
auto member = dyn_cast<ValueDecl>(_member);
2954-
if (!member || isa<AccessorDecl>(member) || member->getOverriddenDecl())
2953+
if (!member || isa<AccessorDecl>(member))
2954+
continue;
2955+
2956+
ASTContext &ctx = member->getASTContext();
2957+
2958+
// Also skip overrides, unless they override an unavailable decl, which
2959+
// makes them not formally overrides anymore.
2960+
if (member->getOverriddenDecl() &&
2961+
!member->getOverriddenDecl()->getAttrs().isUnavailable(ctx))
29552962
continue;
29562963

29572964
// Skip alternate Swift names for other language modes.
2958-
if (member->getAttrs().isUnavailable(member->getASTContext()))
2965+
if (member->getAttrs().isUnavailable(ctx))
29592966
continue;
29602967

29612968
// Skip async versions of members. We'll match against the completion

test/decl/ext/Inputs/objc_implementation.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
@interface ObjCBaseClass
44

5+
- (instancetype)init __attribute__((unavailable));
56

67
// Need two initializers to reproduce certain conflict bugs.
78
- (instancetype)initFromSuperclass:(int)param __attribute__((objc_designated_initializer));
@@ -161,6 +162,12 @@
161162

162163
@end
163164

165+
@interface ObjCBasicInitClass : ObjCBaseClass
166+
167+
- (nonnull instancetype)init __attribute__((objc_designated_initializer));
168+
169+
@end
170+
164171

165172

166173
struct ObjCStruct {

test/decl/ext/objc_implementation.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,12 @@ protocol EmptySwiftProto {}
393393
}
394394
}
395395

396+
@_objcImplementation extension ObjCBasicInitClass {
397+
init() {
398+
// OK
399+
}
400+
}
401+
396402
@_objcImplementation extension ObjCClass {}
397403
// expected-error@-1 {{duplicate implementation of Objective-C class 'ObjCClass'}}
398404

0 commit comments

Comments
 (0)