1010//
1111// ===----------------------------------------------------------------------===//
1212
13+ #include " Cleanup.h"
1314#include " Initialization.h"
1415#include " LValue.h"
1516#include " RValue.h"
@@ -682,10 +683,18 @@ namespace {
682683
683684static void deallocateAddressable (SILGenFunction &SGF,
684685 SILLocation l,
685- const SILGenFunction::AddressableBuffer::State &state) {
686- SGF.B .createEndBorrow (l, state.storeBorrow );
686+ const SILGenFunction::AddressableBuffer::State &state,
687+ CleanupState cleanupState) {
688+ // Only delete the value if the variable was active on this path.
689+ // The stack slot exists within the variable scope regardless, so always
690+ // needs to be cleaned up.
691+ bool active = isActiveCleanupState (cleanupState);
692+ if (active) {
693+ SGF.B .createEndBorrow (l, state.storeBorrow );
694+ }
687695 SGF.B .createDeallocStack (l, state.allocStack );
688- if (state.reabstraction
696+ if (active
697+ && state.reabstraction
689698 && !state.reabstraction ->getType ().isTrivial (SGF.F )) {
690699 SGF.B .createDestroyValue (l, state.reabstraction );
691700 }
@@ -695,8 +704,11 @@ static void deallocateAddressable(SILGenFunction &SGF,
695704// / binding.
696705class DeallocateLocalVariableAddressableBuffer : public Cleanup {
697706 ValueDecl *vd;
707+ CleanupHandle destroyVarHandle;
698708public:
699- DeallocateLocalVariableAddressableBuffer (ValueDecl *vd) : vd(vd) {}
709+ DeallocateLocalVariableAddressableBuffer (ValueDecl *vd,
710+ CleanupHandle destroyVarHandle)
711+ : vd(vd), destroyVarHandle(destroyVarHandle) {}
700712
701713 void emit (SILGenFunction &SGF, CleanupLocation l,
702714 ForUnwind_t forUnwind) override {
@@ -705,14 +717,20 @@ class DeallocateLocalVariableAddressableBuffer : public Cleanup {
705717 return ;
706718 }
707719
720+ // Reflect the state of the variable's original cleanup.
721+ CleanupState cleanupState = CleanupState::Active;
722+ if (destroyVarHandle.isValid ()) {
723+ cleanupState = SGF.Cleanups .getCleanup (destroyVarHandle).getState ();
724+ }
725+
708726 if (auto *state = addressableBuffer->getState ()) {
709- // The addressable buffer was forced, so clean it up now.
710- deallocateAddressable (SGF, l, *state);
727+ // The addressable buffer was already forced, so clean up now.
728+ deallocateAddressable (SGF, l, *state, cleanupState );
711729 } else {
712730 // Remember this insert location in case we need to force the addressable
713731 // buffer later.
714732 SILInstruction *marker = SGF.B .createTuple (l, {});
715- addressableBuffer->cleanupPoints .emplace_back ( marker);
733+ addressableBuffer->cleanupPoints .push_back ({ marker, cleanupState} );
716734 }
717735 }
718736
@@ -820,7 +838,7 @@ class LetValueInitialization : public Initialization {
820838
821839 // If the binding has an addressable buffer forced, it should be cleaned
822840 // up at this scope.
823- SGF.enterLocalVariableAddressableBufferScope (vd);
841+ SGF.enterLocalVariableAddressableBufferScope (vd, DestroyCleanup );
824842 }
825843
826844 ~LetValueInitialization () override {
@@ -2237,10 +2255,11 @@ void SILGenFunction::destroyLocalVariable(SILLocation silLoc, VarDecl *vd) {
22372255}
22382256
22392257void
2240- SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl) {
2258+ SILGenFunction::enterLocalVariableAddressableBufferScope (VarDecl *decl,
2259+ CleanupHandle destroyCleanup) {
22412260 auto marker = B.createTuple (decl, {});
22422261 AddressableBuffers[decl].insertPoint = marker;
2243- Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl);
2262+ Cleanups.pushCleanup <DeallocateLocalVariableAddressableBuffer>(decl, destroyCleanup );
22442263}
22452264
22462265SILValue
@@ -2355,10 +2374,11 @@ SILGenFunction::getLocalVariableAddressableBuffer(VarDecl *decl,
23552374 decltype (addressableBuffer->cleanupPoints ) cleanupPoints;
23562375 cleanupPoints.swap (addressableBuffer->cleanupPoints );
23572376
2358- for (SILInstruction *cleanupPoint : cleanupPoints) {
2359- SavedInsertionPointRAII insertCleanup (B, cleanupPoint);
2360- deallocateAddressable (*this , cleanupPoint->getLoc (), *newState);
2361- cleanupPoint->eraseFromParent ();
2377+ for (auto &cleanupPoint : cleanupPoints) {
2378+ SavedInsertionPointRAII insertCleanup (B, cleanupPoint.inst );
2379+ deallocateAddressable (*this , cleanupPoint.inst ->getLoc (), *newState,
2380+ cleanupPoint.state );
2381+ cleanupPoint.inst ->eraseFromParent ();
23622382 }
23632383
23642384 return storeBorrow;
@@ -2400,8 +2420,8 @@ SILGenFunction::AddressableBuffer::~AddressableBuffer() {
24002420 if (insertPoint) {
24012421 insertPoint->eraseFromParent ();
24022422 }
2403- for (auto cleanupPoint : cleanupPoints) {
2404- cleanupPoint->eraseFromParent ();
2423+ for (auto & cleanupPoint : cleanupPoints) {
2424+ cleanupPoint. inst ->eraseFromParent ();
24052425 }
24062426 if (auto state = stateOrAlias.dyn_cast <State*>()) {
24072427 delete state;
0 commit comments