Skip to content

Commit 3620aee

Browse files
committed
Sema: Fix for derived classes where the base class has inaccessible initializers
If the base class is in a different module and defines an internal initializer, or it is in a different file and defines a private initializer, the subclass cannot access this initializer. Fix this by insisting on synthesizing initializers even if they override an internal or private initializer in the base class. In this case, synthesize them as a stub instead of a chaining initializer. They cannot be called, and they cannot reference the superclass initializer, so a stub is appropriate here. Also in SILGen, emit vtable entries for stub initializers unless they are overriding an Objective-C initializer.
1 parent 7623708 commit 3620aee

File tree

4 files changed

+28
-9
lines changed

4 files changed

+28
-9
lines changed

lib/SILGen/SILGenType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,9 @@ class SILGenVTable : public Lowering::ASTVisitor<SILGenVTable> {
243243
}
244244

245245
void visitConstructorDecl(ConstructorDecl *cd) {
246-
// Stub constructors don't get an entry.
247-
if (cd->hasStubImplementation())
246+
// Stub constructors don't get an entry, unless they were synthesized to
247+
// override a non-required designated initializer in the superclass.
248+
if (cd->hasStubImplementation() && !cd->getOverriddenDecl())
248249
return;
249250

250251
// Required constructors (or overrides thereof) have their allocating entry

lib/Sema/CodeSynthesis.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2155,7 +2155,7 @@ swift::createDesignatedInitOverride(TypeChecker &tc,
21552155

21562156
// Wire up the overrides.
21572157
ctor->getAttrs().add(new (tc.Context) OverrideAttr(/*Implicit=*/true));
2158-
checkOverrides(tc, ctor);
2158+
ctor->setOverriddenDecl(superclassCtor);
21592159

21602160
if (kind == DesignatedInitKind::Stub) {
21612161
// Make this a stub implementation.

lib/Sema/TypeCheckDecl.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7547,7 +7547,10 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
75477547
}
75487548

75497549
auto superclassTy = classDecl->getSuperclass();
7550-
for (auto memberResult : lookupConstructors(classDecl, superclassTy)) {
7550+
auto ctors = lookupConstructors(classDecl, superclassTy,
7551+
NameLookupFlags::IgnoreAccessibility);
7552+
7553+
for (auto memberResult : ctors) {
75517554
auto member = memberResult.Decl;
75527555

75537556
// Skip unavailable superclass initializers.
@@ -7595,12 +7598,23 @@ void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
75957598
getInitializerParamType(superclassCtor)).second)
75967599
continue;
75977600

7601+
// If we're inheriting initializers, create an override delegating
7602+
// to 'super.init'. Otherwise, create a stub which traps at runtime.
7603+
auto kind = canInheritInitializers
7604+
? DesignatedInitKind::Chaining
7605+
: DesignatedInitKind::Stub;
7606+
7607+
// If the superclass initializer is not accessible from the derived
7608+
// class, we cannot chain to 'super.init' either -- create a stub.
7609+
if (!superclassCtor->isAccessibleFrom(classDecl)) {
7610+
assert(!superclassCtor->isRequired() &&
7611+
"required initializer less visible than the class?");
7612+
kind = DesignatedInitKind::Stub;
7613+
}
7614+
75987615
// We have a designated initializer. Create an override of it.
75997616
if (auto ctor = createDesignatedInitOverride(
7600-
*this, classDecl, superclassCtor,
7601-
canInheritInitializers
7602-
? DesignatedInitKind::Chaining
7603-
: DesignatedInitKind::Stub)) {
7617+
*this, classDecl, superclassCtor, kind)) {
76047618
classDecl->addMember(ctor);
76057619
}
76067620
}

test/SILGen/accessibility_vtables.swift

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@ class Sub : Base {
1212
}
1313
}
1414

15+
// CHECK-LABEL: sil hidden @_TFC21accessibility_vtables3SubcfT_S0_ : $@convention(method) (@owned Sub) -> @owned Sub
16+
// CHECK: bb0(%0 : $Sub):
17+
// CHECK: function_ref @_TFs26_unimplemented_initializerFT9classNameVs12StaticString8initNameS_4fileS_4lineSu6columnSu_T_
18+
1519
// CHECK-LABEL: sil_vtable Sub {
1620
// CHECK-NEXT: #Base.internalMethod!1: _TFC28accessibility_vtables_helper4Base14internalMethod
1721
// CHECK-NEXT: #Base.prop!getter.1: _TFC21accessibility_vtables3Subg4propSi // accessibility_vtables.Sub.prop.getter : Swift.Int
1822
// CHECK-NEXT: #Base.prop!setter.1: _TFC28accessibility_vtables_helper4Bases4propSi // accessibility_vtables_helper.Base.prop.setter : Swift.Int
1923
// CHECK-NEXT: #Base.prop!materializeForSet.1: _TFC28accessibility_vtables_helper4Basem4propSi // accessibility_vtables_helper.Base.prop.materializeForSet : Swift.Int
20-
// CHECK-NEXT: #Base.init!initializer.1: _TFC28accessibility_vtables_helper4Basec
24+
// CHECK-NEXT: #Base.init!initializer.1: _TFC21accessibility_vtables3SubcfT_S0_ // accessibility_vtables.Sub.init () -> accessibility_vtables.Sub
2125
// CHECK-NEXT: #Sub.internalMethod!1: _TFC21accessibility_vtables3Sub14internalMethod
2226
// CHECK-NEXT: #Sub.prop!setter.1: _TFC21accessibility_vtables3Subs4propSi // accessibility_vtables.Sub.prop.setter : Swift.Int
2327
// CHECK-NEXT: #Sub.prop!materializeForSet.1: _TFC21accessibility_vtables3Subm4propSi // accessibility_vtables.Sub.prop.materializeForSet : Swift.Int

0 commit comments

Comments
 (0)