Skip to content

Commit 5c5de29

Browse files
authored
Merge pull request #25678 from slavapestov/vtable-thunk-final-bug
SILGen: Fix generated vtable thunk when a final override is more visible than the base
2 parents 88a5c00 + e2d660f commit 5c5de29

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

lib/SILGen/SILGenType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ SILGenModule::emitVTableMethod(ClassDecl *theClass,
9696
// If the base method is less visible than the derived method, we need
9797
// a thunk.
9898
bool baseLessVisibleThanDerived =
99-
(derivedDecl->isEffectiveLinkageMoreVisibleThan(baseDecl) &&
100-
!usesObjCDynamicDispatch);
99+
(!usesObjCDynamicDispatch &&
100+
!derivedDecl->isFinal() &&
101+
derivedDecl->isEffectiveLinkageMoreVisibleThan(baseDecl));
101102

102103
// Determine the derived thunk type by lowering the derived type against the
103104
// abstraction pattern of the base.

test/Interpreter/Inputs/vtables_multifile_2.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ open class Derived : Base {
1313
}
1414
}
1515

16+
public final class FinalDerived : Base {
17+
public override func privateMethod() -> Int {
18+
return super.privateMethod() + 1
19+
}
20+
}
21+
1622
public func callBaseMethod(_ b: Base) -> Int {
1723
return b.privateMethod()
1824
}

test/Interpreter/vtables_multifile.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,12 @@ open class OtherDerived : Derived {
2121
}
2222
}
2323

24+
public final class OtherFinalDerived : Derived {
25+
public override func privateMethod() -> Int {
26+
return super.privateMethod() + 1
27+
}
28+
}
29+
2430
VTableTestSuite.test("Base") {
2531
expectEqual(1, callBaseMethod(Base()))
2632
}
@@ -35,4 +41,9 @@ VTableTestSuite.test("OtherDerived") {
3541
expectEqual(3, callDerivedMethod(OtherDerived()))
3642
}
3743

44+
VTableTestSuite.test("OtherFinalDerived") {
45+
expectEqual(3, callBaseMethod(OtherFinalDerived()))
46+
expectEqual(3, callDerivedMethod(OtherFinalDerived()))
47+
}
48+
3849
runAllTests()

test/SILGen/vtables_multifile.swift

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,13 @@ open class MostDerived : MoreDerived {
3434
open override func privateMethod4(_: Int) {}
3535
}
3636

37+
public final class FinalDerived : Base<Int> {
38+
internal override func privateMethod1() {}
39+
internal override func privateMethod2(_: AnyObject?) {}
40+
internal override func privateMethod3(_: Int?) {}
41+
internal override func privateMethod4(_: Int) {}
42+
}
43+
3744
// See Inputs/vtables_multifile_2.swift for overrides in a different file.
3845
// See Inputs/vtables_multifile_3.swift for overrides in a different module.
3946

@@ -127,7 +134,6 @@ open class MostDerived : MoreDerived {
127134
// CHECK-NEXT: return [[RESULT]] : $()
128135
// CHECK-NEXT: }
129136

130-
// vtable thunk for Derived.privateMethod2(_:) dispatching to MoreDerived.privateMethod2(_:)
131137
// CHECK-LABEL: sil private [ossa] @$s17vtables_multifile11MoreDerivedC14privateMethod2yyyXlSgFAA0D0CADyyAEFTV : $@convention(method) (@guaranteed Optional<AnyObject>, @guaranteed MoreDerived) -> () {
132138
// CHECK: bb0(%0 : @guaranteed $Optional<AnyObject>, %1 : @guaranteed $MoreDerived):
133139
// CHECK-NEXT: [[METHOD:%.*]] = class_method %1 : $MoreDerived, #MoreDerived.privateMethod2!1 : (MoreDerived) -> (AnyObject?) -> (), $@convention(method) (@guaranteed Optional<AnyObject>, @guaranteed MoreDerived) -> ()
@@ -136,7 +142,6 @@ open class MostDerived : MoreDerived {
136142
// CHECK-NEXT: return [[RESULT]] : $()
137143
// CHECK-NEXT: }
138144

139-
// vtable thunk for Derived.privateMethod3(_:) dispatching to MoreDerived.privateMethod3(_:)
140145
// CHECK-LABEL: il private [ossa] @$s17vtables_multifile11MoreDerivedC14privateMethod3yySiSgFAA0D0CADyyAEFTV : $@convention(method) (Optional<Int>, @guaranteed MoreDerived) -> () {
141146
// CHECK: bb0(%0 : $Optional<Int>, %1 : @guaranteed $MoreDerived):
142147
// CHECK-NEXT: [[METHOD:%.*]] = class_method %1 : $MoreDerived, #MoreDerived.privateMethod3!1 : (MoreDerived) -> (Int?) -> (), $@convention(method) (Optional<Int>, @guaranteed MoreDerived) -> ()
@@ -145,7 +150,6 @@ open class MostDerived : MoreDerived {
145150
// CHECK-NEXT: return [[RESULT]] : $()
146151
// CHECK-NEXT: }
147152

148-
// vtable thunk for Derived.privateMethod4(_:) dispatching to MoreDerived.privateMethod4(_:)
149153
// CHECK-LABEL: sil private [ossa] @$s17vtables_multifile11MoreDerivedC14privateMethod4yySiFAA0D0CADyySiFTV : $@convention(method) (Int, @guaranteed MoreDerived) -> () {
150154
// CHECK: bb0(%0 : $Int, %1 : @guaranteed $MoreDerived):
151155
// CHECK-NEXT: [[METHOD:%.*]] = class_method %1 : $MoreDerived, #MoreDerived.privateMethod4!1 : (MoreDerived) -> (Int) -> (), $@convention(method) (Int, @guaranteed MoreDerived) -> ()
@@ -154,6 +158,30 @@ open class MostDerived : MoreDerived {
154158
// CHECK-NEXT: return [[RESULT]] : $()
155159
// CHECK-NEXT: }
156160

161+
// --
162+
// Thunks for final overrides do not re-dispatch, even if the override is more
163+
// visible.
164+
// --
165+
166+
// CHECK-LABEL: sil private [ossa] @$s17vtables_multifile12FinalDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV : $@convention(method) (Int, @guaranteed FinalDerived) -> () {
167+
// CHECK: bb0(%0 : $Int, %1 : @guaranteed $FinalDerived):
168+
// CHECK-NEXT: [[ARG:%.*]] = enum $Optional<Int>, #Optional.some!enumelt.1, %0 : $Int // user: %4
169+
// CHECK: [[METHOD:%.*]] = function_ref @$s17vtables_multifile12FinalDerivedC14privateMethod3yySiSgF : $@convention(method) (Optional<Int>, @guaranteed FinalDerived) -> ()
170+
// CHECK-NEXT: apply [[METHOD]]([[ARG]], %1) : $@convention(method) (Optional<Int>, @guaranteed FinalDerived) -> ()
171+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
172+
// CHECK-NEXT: return [[RESULT]] : $()
173+
// CHECK-NEXT: }
174+
175+
// CHECK-LABEL: sil private [ossa] @$s17vtables_multifile12FinalDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV : $@convention(method) (@in_guaranteed Int, @guaranteed FinalDerived) -> () {
176+
// CHECK: bb0(%0 : $*Int, %1 : @guaranteed $FinalDerived):
177+
// CHECK-NEXT: [[ARG:%.*]] = load [trivial] %0 : $*Int
178+
// CHECK: [[METHOD:%.*]] = function_ref @$s17vtables_multifile12FinalDerivedC14privateMethod4yySiF : $@convention(method) (Int, @guaranteed FinalDerived) -> ()
179+
// CHECK-NEXT: [[RESULT:%.*]] = apply [[METHOD]]([[ARG]], %1) : $@convention(method) (Int, @guaranteed FinalDerived) -> ()
180+
// CHECK-NEXT: [[RESULT:%.*]] = tuple ()
181+
// CHECK-NEXT: return [[RESULT]] : $()
182+
// CHECK-NEXT: }
183+
184+
157185
// --
158186
// VTable for Derived.
159187
// --
@@ -212,3 +240,16 @@ open class MostDerived : MoreDerived {
212240
// CHECK-NEXT: #MoreDerived.privateMethod4!1: (MoreDerived) -> (Int) -> () : @$s17vtables_multifile11MostDerivedC14privateMethod4yySiF [override] // MostDerived.privateMethod4(_:)
213241
// CHECK-NEXT: #MostDerived.deinit!deallocator.1: @$s17vtables_multifile11MostDerivedCfD // MostDerived.__deallocating_deinit
214242
// CHECK-NEXT: }
243+
244+
// --
245+
// FinalDerived adds a final override; make sure we handle this correctly.
246+
// --
247+
248+
// CHECK-LABEL: sil_vtable [serialized] FinalDerived {
249+
// CHECK-NEXT: #Base.privateMethod1!1: <T> (Base<T>) -> () -> () : @$s17vtables_multifile12FinalDerivedC14privateMethod1yyF [override] // FinalDerived.privateMethod1()
250+
// CHECK-NEXT: #Base.privateMethod2!1: <T> (Base<T>) -> (AnyObject) -> () : @$s17vtables_multifile12FinalDerivedC14privateMethod2yyyXlSgF [override] // FinalDerived.privateMethod2(_:)
251+
// CHECK-NEXT: #Base.privateMethod3!1: <T> (Base<T>) -> (Int) -> () : @$s17vtables_multifile12FinalDerivedC14privateMethod3yySiSgFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyySiFTV [override] // vtable thunk for Base.privateMethod3(_:) dispatching to FinalDerived.privateMethod3(_:)
252+
// CHECK-NEXT: #Base.privateMethod4!1: <T> (Base<T>) -> (T) -> () : @$s17vtables_multifile12FinalDerivedC14privateMethod4yySiFAA4BaseCAD33_63E5F2521A3C787F5F9EFD57FB9237EALLyyxFTV [override] // vtable thunk for Base.privateMethod4(_:) dispatching to FinalDerived.privateMethod4(_:)
253+
// CHECK-NEXT: #Base.init!allocator.1: <T> (Base<T>.Type) -> () -> Base<T> : @$s17vtables_multifile12FinalDerivedCACycfC [override] // FinalDerived.__allocating_init()
254+
// CHECK-NEXT: #FinalDerived.deinit!deallocator.1: @$s17vtables_multifile12FinalDerivedCfD // FinalDerived.__deallocating_deinit
255+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)