@@ -1420,8 +1420,12 @@ void PatternMatchEmission::bindBorrow(Pattern *pattern, VarDecl *var,
14201420 // Create a notional copy for the borrow checker to use.
14211421 bindValue = bindValue.copy (SGF, pattern);
14221422 }
1423+ // We mark the borrow check as "strict" because we don't want to allow
1424+ // consumes through the binding, even if the original value manages to be
1425+ // stack promoted during AllocBoxToStack or anything like that.
14231426 bindValue = SGF.B .createMarkUnresolvedNonCopyableValueInst (pattern, bindValue,
1424- MarkUnresolvedNonCopyableValueInst::CheckKind::NoConsumeOrAssign);
1427+ MarkUnresolvedNonCopyableValueInst::CheckKind::NoConsumeOrAssign,
1428+ MarkUnresolvedNonCopyableValueInst::IsStrict);
14251429
14261430 SGF.VarLocs [var] = SILGenFunction::VarLoc::get (bindValue.getValue ());
14271431}
@@ -3198,6 +3202,26 @@ static void switchCaseStmtSuccessCallback(SILGenFunction &SGF,
31983202 SGF.Cleanups .emitBranchAndCleanups (sharedDest, caseBlock, args);
31993203}
32003204
3205+ class EndAccessCleanup final : public Cleanup {
3206+ SILValue beginAccess;
3207+ public:
3208+ EndAccessCleanup (SILValue beginAccess)
3209+ : beginAccess(beginAccess)
3210+ {}
3211+
3212+ void emit (SILGenFunction &SGF, CleanupLocation loc, ForUnwind_t forUnwind)
3213+ override {
3214+ SGF.B .createEndAccess (loc, beginAccess, /* aborted*/ false );
3215+ }
3216+
3217+ void dump (SILGenFunction &SGF) const override {
3218+ llvm::errs () << " EndAccessCleanup\n " ;
3219+ if (beginAccess) {
3220+ beginAccess->print (llvm::errs ());
3221+ }
3222+ }
3223+ };
3224+
32013225void SILGenFunction::emitSwitchStmt (SwitchStmt *S) {
32023226 LLVM_DEBUG (llvm::dbgs () << " emitting switch stmt\n " ;
32033227 S->dump (llvm::dbgs ());
@@ -3385,12 +3409,22 @@ void SILGenFunction::emitSwitchStmt(SwitchStmt *S) {
33853409 if (!subjectMV.isPlusZero ()) {
33863410 subjectMV = subjectMV.borrow (*this , S);
33873411 }
3388- if (subjectMV.getType ().isAddress () &&
3389- subjectMV.getType ().isLoadable (F)) {
3390- // Load a borrow if the type is loadable.
3391- subjectMV = subjectUndergoesFormalAccess
3392- ? B.createFormalAccessLoadBorrow (S, subjectMV)
3393- : B.createLoadBorrow (S, subjectMV);
3412+ if (subjectMV.getType ().isAddress ()) {
3413+ if (subjectMV.getType ().isLoadable (F)) {
3414+ // Load a borrow if the type is loadable.
3415+ subjectMV = subjectUndergoesFormalAccess
3416+ ? B.createFormalAccessLoadBorrow (S, subjectMV)
3417+ : B.createLoadBorrow (S, subjectMV);
3418+ } else {
3419+ // Initiate a read access on the memory, to ensure that even
3420+ // if the underlying memory is mutable or consumable, the pattern
3421+ // match is not allowed to modify it.
3422+ auto access = B.createBeginAccess (S, subjectMV.getValue (),
3423+ SILAccessKind::Read,
3424+ SILAccessEnforcement::Static, false , false );
3425+ Cleanups.pushCleanup <EndAccessCleanup>(access);
3426+ subjectMV = ManagedValue::forBorrowedAddressRValue (access);
3427+ }
33943428 }
33953429 return {subjectMV, CastConsumptionKind::BorrowAlways};
33963430
0 commit comments