Skip to content

Commit 5881ea4

Browse files
committed
[DI] Fix unfailable throw during super init.
When deallocating a partially allocated class in the trapping branch of an unfailable cast, cast back down to the subclass which is being partially deallocated before emitting the dealloc partial ref instruction.
1 parent 46ccdd6 commit 5881ea4

File tree

3 files changed

+118
-0
lines changed

3 files changed

+118
-0
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -2642,6 +2642,12 @@ void LifetimeChecker::processUninitializedRelease(SILInstruction *Release,
26422642
}
26432643
}
26442644

2645+
// Cast back down from an upcast.
2646+
if (auto *UI = dyn_cast<UpcastInst>(Pointer)) {
2647+
Pointer =
2648+
B.createUncheckedRefCast(Loc, Pointer, UI->getOperand()->getType());
2649+
}
2650+
26452651
// We've already destroyed any instance variables initialized by this
26462652
// constructor, now destroy instance variables initialized by subclass
26472653
// constructors that delegated to us, and finally free the memory.

test/SILOptimizer/definite_init.swift

+12
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,15 @@ class AgainCheckCompilerInitAttr {
7676
whenever = 0
7777
} // expected-error {{return from initializer without initializing all stored properties}}
7878
}
79+
80+
class Super {
81+
init(_ i: Int) {}
82+
}
83+
84+
class Sub : Super {
85+
init() {
86+
super.init(try! get())
87+
}
88+
}
89+
90+
func get() throws -> Int { 0 }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// RUN: %target-sil-opt -enable-sil-verify-all %s -definite-init -raw-sil-inst-lowering | %FileCheck %s
2+
3+
// These are all regression tests to ensure that the memory promotion pass
4+
// doesn't crash.
5+
6+
// REQUIRES: objc_interop
7+
8+
import Builtin
9+
import Swift
10+
import Foundation
11+
12+
sil @$ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_line17_isImplicitUnwrapyBp_BwBi1_BwBi1_tF : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
13+
sil @superinit : $@convention(method) (@in Any, @owned Super) -> @owned Super
14+
sil [exact_self_class] [ossa] @$s4main5SuperCyACypcfC : $@convention(method) (@in Any, @thick Super.Type) -> @owned Super
15+
sil [ossa] @$s4main5SuperCfD : $@convention(method) (@owned Super) -> ()
16+
sil [ossa] @$s4main3SubCfD : $@convention(method) (@owned Sub) -> ()
17+
sil [exact_self_class] [ossa] @$s4main3SubCyACSo8NSStringCcfC : $@convention(method) (@owned NSString, @thick Sub.Type) -> @owned Sub
18+
19+
class Super {
20+
var t: Any
21+
init(_ t: Any) {
22+
self.t = t
23+
}
24+
}
25+
26+
class Sub : Super {
27+
init(_ i: NSString) {
28+
super.init(i.lowercased as NSString)
29+
}
30+
}
31+
32+
33+
// CHECK-LABEL: sil hidden [ossa] @cast_to_nsstring : {{.*}} {
34+
// CHECK: [[STACK:%[^,]+]] = alloc_stack
35+
// CHECK: [[SUB_1:%[^,]+]] = load [take] [[STACK]]
36+
// CHECK: [[SUPER_1:%[^,]+]] = upcast [[SUB_1]] : $Sub to $Super
37+
// CHECK: switch_enum
38+
// CHECK-SAME: case #Optional.none!enumelt: [[NONE:bb[0-9]+]]
39+
// CHECK: [[NONE]]:
40+
// CHECK: [[SUB_META_1:%[^,]+]] = metatype $@thick Sub.Type
41+
// CHECK: [[SUB_1:%[^,]+]] = unchecked_ref_cast [[SUPER_1]] : $Super to $Sub
42+
// CHECK: dealloc_partial_ref
43+
// CHECK-SAME: [[SUB_1]]
44+
// CHECK-SAME: [[SUB_META_1]]
45+
// CHECK: [[SUB_1:%[^,]+]] = load [take] [[STACK]]
46+
// CHECK: [[SUB_META_1:%[^,]+]] = metatype $@thick Sub.Type
47+
// CHECK: dealloc_partial_ref
48+
// CHECK-SAME: [[SUB_1]]
49+
// CHECK-SAME: [[SUB_META_1]]
50+
// CHECK-LABEL: } // end sil function 'cast_to_nsstring'
51+
sil hidden [ossa] @cast_to_nsstring : $@convention(method) (@owned NSString, @owned Sub) -> @owned Sub {
52+
bb0(%0 : @owned $NSString, %1 : @owned $Sub):
53+
%2 = alloc_stack [lexical] [var_decl] $Sub
54+
%3 = mark_uninitialized [derivedself] %2 : $*Sub
55+
store %1 to [init] %3 : $*Sub
56+
%6 = load [take] %3 : $*Sub
57+
%7 = upcast %6 : $Sub to $Super
58+
%8 = alloc_stack $Any
59+
%9 = objc_method %0 : $NSString, #NSString.lowercased!getter.foreign : (NSString) -> () -> String, $@convention(objc_method) (NSString) -> @autoreleased Optional<NSString>
60+
%10 = apply %9(%0) : $@convention(objc_method) (NSString) -> @autoreleased Optional<NSString>
61+
switch_enum %10 : $Optional<NSString>, case #Optional.some!enumelt: bb2, case #Optional.none!enumelt: bb1
62+
63+
bb1:
64+
destroy_value %7 : $Super
65+
%13 = string_literal utf8 "main/main.swift"
66+
%14 = integer_literal $Builtin.Word, 15
67+
%15 = integer_literal $Builtin.Int1, -1
68+
%16 = integer_literal $Builtin.Word, 14
69+
%17 = integer_literal $Builtin.Word, 18
70+
%18 = integer_literal $Builtin.Int1, -1
71+
%19 = function_ref @$ss30_diagnoseUnexpectedNilOptional14_filenameStart01_E6Length01_E7IsASCII5_line17_isImplicitUnwrapyBp_BwBi1_BwBi1_tF : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
72+
%20 = apply %19(%13, %14, %15, %16, %18) : $@convention(thin) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, Builtin.Word, Builtin.Int1) -> ()
73+
destroy_addr %3 : $*Sub
74+
destroy_value %0 : $NSString
75+
unreachable
76+
77+
bb2(%24 : @owned $NSString):
78+
%25 = init_existential_addr %8 : $*Any, $NSString
79+
store %24 to [init] %25 : $*NSString
80+
%27 = function_ref @superinit : $@convention(method) (@in Any, @owned Super) -> @owned Super
81+
%28 = apply %27(%8, %7) : $@convention(method) (@in Any, @owned Super) -> @owned Super
82+
dealloc_stack %8 : $*Any
83+
%30 = unchecked_ref_cast %28 : $Super to $Sub
84+
store %30 to [init] %3 : $*Sub
85+
%32 = load [copy] %3 : $*Sub
86+
destroy_value %0 : $NSString
87+
destroy_addr %3 : $*Sub
88+
dealloc_stack %2 : $*Sub
89+
return %32 : $Sub
90+
}
91+
92+
sil_vtable Super {
93+
#Super.init!allocator: (Super.Type) -> (Any) -> Super : @$s4main5SuperCyACypcfC
94+
#Super.deinit!deallocator: @$s4main5SuperCfD
95+
}
96+
97+
sil_vtable Sub {
98+
#Sub.init!allocator: (Sub.Type) -> (NSString) -> Sub : @$s4main3SubCyACSo8NSStringCcfC
99+
#Sub.deinit!deallocator: @$s4main3SubCfD
100+
}

0 commit comments

Comments
 (0)