Skip to content

Commit 21a4d54

Browse files
authored
Merge pull request #22449 from gottesmm/pr-fb26d1bf402324ef5ab4eac767964caff06d3e39
[silgenpattern] Fix the box handling in the old silgenpattern enum co…
2 parents 920b2f7 + d364bb3 commit 21a4d54

File tree

3 files changed

+72
-6
lines changed

3 files changed

+72
-6
lines changed

lib/SILGen/SILGenPattern.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2165,15 +2165,14 @@ void PatternMatchEmission::emitEnumElementDispatch(
21652165
auto accessMV = ManagedValue::forUnmanaged(accessAddress);
21662166
ManagedValue newLoadedBoxValue;
21672167
if (accessAddress == boxedValue) {
2168-
newLoadedBoxValue = SGF.B.createLoadBorrow(loc, accessMV);
2168+
eltCMV = {SGF.B.createLoadBorrow(loc, accessMV),
2169+
CastConsumptionKind::BorrowAlways};
21692170
} else {
2170-
newLoadedBoxValue = SGF.B.createLoadCopy(loc, accessMV);
2171+
// Since we made a copy, send down TakeAlways.
2172+
eltCMV = {SGF.B.createLoadCopy(loc, accessMV),
2173+
CastConsumptionKind::TakeAlways};
21712174
}
2172-
boxedValue = newLoadedBoxValue.getUnmanagedValue();
21732175
access.endAccess(SGF);
2174-
2175-
// Since we made a copy, send down TakeAlways.
2176-
eltCMV = {newLoadedBoxValue, CastConsumptionKind::TakeAlways};
21772176
} else {
21782177
// The boxed value may be shared, so we always have to copy it.
21792178
eltCMV = getManagedSubobject(SGF, boxedValue, *eltTL,

test/Interpreter/indirect_enum.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// RUN: %target-swiftc_driver %s -target %sanitizers-target-triple -g -sanitize=address -o %t_asan-binary
2+
// RUN: %target-codesign %t_asan-binary
3+
// RUN: env ASAN_OPTIONS=detect_leaks=0 %target-run %t_asan-binary
4+
// REQUIRES: executable_test
5+
// REQUIRES: asan_runtime
6+
7+
// Make sure that we do not use-after-free here.
8+
9+
class Box<T> {
10+
var value: T
11+
init(_ inputValue: T) { value = inputValue }
12+
}
13+
14+
enum Value<U> {
15+
case inline(U)
16+
indirect case box(Box<U>)
17+
}
18+
19+
func evaluate<U>(_ v: Value<U>) {
20+
switch v {
21+
case .inline:
22+
return print("foo")
23+
case .box(let box):
24+
return print("bar \(box)")
25+
}
26+
}
27+
28+
func main() {
29+
let v = Value.box(Box<[Int]>([1, 2, 3]))
30+
evaluate(v)
31+
print(v)
32+
}
33+
34+
main()
35+

test/SILGen/indirect_enum.swift

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,3 +541,35 @@ func dontDisableCleanupOfIndirectPayload(_ x: TrivialButIndirect) {
541541
guard case .Indirect(let bar) = x else { return }
542542
}
543543
// CHECK: } // end sil function '$s13indirect_enum35dontDisableCleanupOfIndirectPayloadyyAA010TrivialButG0OF'
544+
545+
// Make sure that in these cases we do not break any ownership invariants.
546+
class Box<T> {
547+
var value: T
548+
init(_ inputValue: T) { value = inputValue }
549+
}
550+
551+
enum ValueWithInlineStorage<T> {
552+
case inline(T)
553+
indirect case box(Box<T>)
554+
}
555+
556+
func switchValueWithInlineStorage<U>(v: ValueWithInlineStorage<U>) {
557+
switch v {
558+
case .inline:
559+
return
560+
case .box(let box):
561+
return
562+
}
563+
}
564+
565+
func guardValueWithInlineStorage<U>(v: ValueWithInlineStorage<U>) {
566+
do {
567+
guard case .inline = v else { return }
568+
guard case .box(let box) = v else { return }
569+
}
570+
571+
do {
572+
if case .inline = v { return }
573+
if case .box(let box) = v { return }
574+
}
575+
}

0 commit comments

Comments
 (0)