Skip to content

Commit 55c919f

Browse files
authored
Merge pull request #22989 from slavapestov/ctor-subclass-scope
SIL: Fix subclass scope calculation for constructors
2 parents f1d1df3 + 2ae6dac commit 55c919f

File tree

3 files changed

+32
-13
lines changed

3 files changed

+32
-13
lines changed

lib/SIL/SILDeclRef.cpp

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -944,47 +944,62 @@ SubclassScope SILDeclRef::getSubclassScope() const {
944944
if (!hasDecl())
945945
return SubclassScope::NotApplicable;
946946

947+
auto *decl = getDecl();
948+
949+
if (!isa<AbstractFunctionDecl>(decl))
950+
return SubclassScope::NotApplicable;
951+
947952
// If this declaration is a function which goes into a vtable, then it's
948953
// symbol must be as visible as its class, because derived classes have to put
949954
// all less visible methods of the base class into their vtables.
950955

951-
if (auto *CD = dyn_cast<ConstructorDecl>(getDecl()))
952-
if (!CD->isRequired())
956+
if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
957+
// Initializing entry points do not appear in the vtable.
958+
if (kind == SILDeclRef::Kind::Initializer)
953959
return SubclassScope::NotApplicable;
954-
955-
auto *FD = dyn_cast<FuncDecl>(getDecl());
956-
if (!FD)
960+
// Non-required convenience inits do not apper in the vtable.
961+
if (!CD->isRequired() && !CD->isDesignatedInit())
962+
return SubclassScope::NotApplicable;
963+
} else if (isa<DestructorDecl>(decl)) {
964+
// Detructors do not appear in the vtable.
957965
return SubclassScope::NotApplicable;
966+
} else {
967+
assert(isa<FuncDecl>(decl));
968+
}
958969

959-
DeclContext *context = FD->getDeclContext();
970+
DeclContext *context = decl->getDeclContext();
960971

961-
// Methods from extensions don't go into vtables (yet).
972+
// Methods from extensions don't go in the vtable.
962973
if (isa<ExtensionDecl>(context))
963974
return SubclassScope::NotApplicable;
964975

965976
// Various forms of thunks don't either.
966977
if (isThunk() || isForeign)
967978
return SubclassScope::NotApplicable;
968979

969-
// Default arg generators are not visible.
980+
// Default arg generators don't go in the vtable.
970981
if (isDefaultArgGenerator())
971982
return SubclassScope::NotApplicable;
972983

984+
// Only non-final methods in non-final classes go in the vtable.
973985
auto *classType = context->getSelfClassDecl();
974986
if (!classType || classType->isFinal())
975987
return SubclassScope::NotApplicable;
976988

977-
if (FD->isFinal())
989+
if (decl->isFinal())
978990
return SubclassScope::NotApplicable;
979991

980-
assert(FD->getEffectiveAccess() <= classType->getEffectiveAccess() &&
992+
assert(decl->getEffectiveAccess() <= classType->getEffectiveAccess() &&
981993
"class must be as visible as its members");
982994

983995
// FIXME: This is too narrow. Any class with resilient metadata should
984996
// probably have this, at least for method overrides that don't add new
985997
// vtable entries.
986-
if (classType->isResilient())
998+
if (classType->isResilient()) {
999+
if (isa<ConstructorDecl>(decl))
1000+
return SubclassScope::NotApplicable;
9871001
return SubclassScope::Resilient;
1002+
}
9881003

9891004
switch (classType->getEffectiveAccess()) {
9901005
case AccessLevel::Private:

test/IRGen/Inputs/vtable_symbol_linkage_base.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ open class Base {
1111
internal var internalVar: Int = 30
1212
}
1313

14+
open class Middle : Base {
15+
public init(x: Int) {}
16+
}
1417

1518
public struct Namespace {
1619
open class Nested {

test/IRGen/vtable_symbol_linkage.swift

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@
1010

1111
import BaseModule
1212

13-
public class Derived : Base {
14-
}
13+
public class Derived : Base {}
14+
15+
public class MostDerived : Middle {}
1516

1617
public class DerivedNested : Namespace.Nested {}
1718
public class DerivedExtNested : Namespace.ExtNested {}

0 commit comments

Comments
 (0)