Skip to content

Commit 37ee480

Browse files
authored
Merge pull request #39037 from gottesmm/pr-47b8f7980de816ebf7790df2bf33c741c95ef64f
[silgen] Ensure that the outer cleanup is emitted along failure paths when initializing sub-tuple patterns
2 parents 5882e03 + be922b9 commit 37ee480

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

lib/SILGen/SILGenDecl.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,16 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
6969
// In the address case, we forward the underlying value and store it
7070
// into memory and then create a +1 cleanup. since we assume here
7171
// that we have a +1 value since we are forwarding into memory.
72+
//
73+
// In order to ensure that we properly clean up along any failure paths, we
74+
// need to mark value as being persistently active. We then unforward it once
75+
// we are done.
7276
assert(value.isPlusOne(SGF) && "Can not store a +0 value into memory?!");
73-
value = ManagedValue::forUnmanaged(value.forward(SGF));
74-
return copyOrInitValueIntoHelper(
77+
CleanupStateRestorationScope valueScope(SGF.Cleanups);
78+
if (value.hasCleanup())
79+
valueScope.pushCleanupState(value.getCleanup(),
80+
CleanupState::PersistentlyActive);
81+
copyOrInitValueIntoHelper(
7582
SGF, loc, value, isInit, SubInitializations,
7683
[&](ManagedValue aggregate, unsigned i,
7784
SILType fieldType) -> ManagedValue {
@@ -83,6 +90,8 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
8390

8491
return SGF.emitManagedRValueWithCleanup(elt.getValue());
8592
});
93+
std::move(valueScope).pop();
94+
value.forward(SGF);
8695
}
8796

8897
void TupleInitialization::finishUninitialized(SILGenFunction &SGF) {

test/SILGen/enum.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,23 @@ func sr7799_1(bar: SR7799??) {
219219
default: print("default")
220220
}
221221
}
222+
223+
// Make sure that we handle enum, tuple initialization composed
224+
// correctly. Previously, we leaked down a failure path due to us misusing
225+
// scopes.
226+
enum rdar81817725 {
227+
case localAddress
228+
case setOption(Int, Any)
229+
230+
static func takeAny(_:Any) -> Bool { return true }
231+
232+
static func testSwitchCleanup(syscall: rdar81817725, expectedLevel: Int,
233+
valueMatcher: (Any) -> Bool)
234+
throws -> Bool {
235+
if case .setOption(expectedLevel, let value) = syscall {
236+
return rdar81817725.takeAny(value)
237+
} else {
238+
return false
239+
}
240+
}
241+
}

0 commit comments

Comments
 (0)