Skip to content

Commit

Permalink
[silgen] Ensure that the outer cleanup is emitted along failure paths…
Browse files Browse the repository at this point in the history
… when initializing sub-tuple patterns

Previously, we would leak in this case along the inner failure path since we had
already forwarded the outer cleanup. Instead in this patch, I change the outer
cleanup to be persistently active (ensuring that failure paths along the
sub-pattern are cleaned up appropriately) and forward it manually afterwards
ensuring that we do not /actually/ emit the cleanup along the success path.

rdar://81817725
  • Loading branch information
gottesmm authored and shahmishal committed Sep 20, 2021
1 parent 8e6c109 commit 30ff21e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 2 deletions.
13 changes: 11 additions & 2 deletions lib/SILGen/SILGenDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,16 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,
// In the address case, we forward the underlying value and store it
// into memory and then create a +1 cleanup. since we assume here
// that we have a +1 value since we are forwarding into memory.
//
// In order to ensure that we properly clean up along any failure paths, we
// need to mark value as being persistently active. We then unforward it once
// we are done.
assert(value.isPlusOne(SGF) && "Can not store a +0 value into memory?!");
value = ManagedValue::forUnmanaged(value.forward(SGF));
return copyOrInitValueIntoHelper(
CleanupStateRestorationScope valueScope(SGF.Cleanups);
if (value.hasCleanup())
valueScope.pushCleanupState(value.getCleanup(),
CleanupState::PersistentlyActive);
copyOrInitValueIntoHelper(
SGF, loc, value, isInit, SubInitializations,
[&](ManagedValue aggregate, unsigned i,
SILType fieldType) -> ManagedValue {
Expand All @@ -83,6 +90,8 @@ void TupleInitialization::copyOrInitValueInto(SILGenFunction &SGF,

return SGF.emitManagedRValueWithCleanup(elt.getValue());
});
std::move(valueScope).pop();
value.forward(SGF);
}

void TupleInitialization::finishUninitialized(SILGenFunction &SGF) {
Expand Down
20 changes: 20 additions & 0 deletions test/SILGen/enum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,23 @@ func sr7799_1(bar: SR7799??) {
default: print("default")
}
}

// Make sure that we handle enum, tuple initialization composed
// correctly. Previously, we leaked down a failure path due to us misusing
// scopes.
enum rdar81817725 {
case localAddress
case setOption(Int, Any)

static func takeAny(_:Any) -> Bool { return true }

static func testSwitchCleanup(syscall: rdar81817725, expectedLevel: Int,
valueMatcher: (Any) -> Bool)
throws -> Bool {
if case .setOption(expectedLevel, let value) = syscall {
return rdar81817725.takeAny(value)
} else {
return false
}
}
}

0 comments on commit 30ff21e

Please sign in to comment.