From 69fbaf670d3e498dbc2211125d2027104a98b3bc Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Sat, 16 Apr 2022 13:40:30 -0700 Subject: [PATCH] Fixed fallthrough inside 'if' or another break scope --- IDEHelper/Compiler/BfStmtEvaluator.cpp | 32 ++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 3e4771e1..85636c0a 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -5362,7 +5362,7 @@ void BfModule::Visit(BfContinueStatement* continueStmt) // Our mixin may just require that we're injected into a breakable scope } else - Fail("'Continue' not applicable in this block", continueStmt); + Fail("'continue' not applicable in this block", continueStmt); return; } @@ -5417,12 +5417,36 @@ void BfModule::Visit(BfContinueStatement* continueStmt) void BfModule::Visit(BfFallthroughStatement* fallthroughStmt) { UpdateSrcPos(fallthroughStmt); - if ((mCurMethodState->mBreakData == NULL) || (!mCurMethodState->mBreakData->mIRFallthroughBlock)) + BfBreakData* breakData = mCurMethodState->mBreakData; + while (breakData != NULL) { - Fail("'Fallthrough' not applicable in this block", fallthroughStmt); + if (breakData->mIRFallthroughBlock) + break; + breakData = breakData->mPrevBreakData; + } + + if (mCurMethodState->mInDeferredBlock) + { + auto checkScope = mCurMethodState->mCurScope; + while (checkScope != NULL) + { + if (checkScope == breakData->mScope) + break; + if (checkScope->mIsDeferredBlock) + { + Fail("The fallthrough crosses a deferred block boundary", fallthroughStmt); + return; + } + checkScope = checkScope->mPrevScope; + } + } + + if (breakData == NULL) + { + Fail("'fallthrough' not applicable in this block", fallthroughStmt); return; } - EmitDeferredScopeCalls(true, mCurMethodState->mBreakData->mScope, mCurMethodState->mBreakData->mIRFallthroughBlock); + EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRFallthroughBlock); mCurMethodState->mLeftBlockUncond = true; // Not really a return, but handled the same way if (mCurMethodState->mDeferredLocalAssignData != NULL) mCurMethodState->mDeferredLocalAssignData->mHadFallthrough = true;