mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Disallowed certain operations in deferred blocks (ie: returns/breaks)
This commit is contained in:
parent
59b807fa15
commit
9309297295
4 changed files with 121 additions and 29 deletions
|
@ -11174,7 +11174,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
|
||||||
if (auto scopeNode = BfNodeDynCast<BfScopeNode>(allocNode))
|
if (auto scopeNode = BfNodeDynCast<BfScopeNode>(allocNode))
|
||||||
{
|
{
|
||||||
newToken = scopeNode->mScopeToken;
|
newToken = scopeNode->mScopeToken;
|
||||||
allocTarget.mScopeData = mModule->FindScope(scopeNode->mTargetNode);
|
allocTarget.mScopeData = mModule->FindScope(scopeNode->mTargetNode, true);
|
||||||
|
|
||||||
if (autoComplete != NULL)
|
if (autoComplete != NULL)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2613,7 +2613,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
||||||
bfError->mIsWhileSpecializing = isWhileSpecializing;
|
bfError->mIsWhileSpecializing = isWhileSpecializing;
|
||||||
|
|
||||||
if ((mCurMethodState != NULL) && (mCurMethodState->mDeferredCallEmitState != NULL) && (mCurMethodState->mDeferredCallEmitState->mCloseNode != NULL))
|
if ((mCurMethodState != NULL) && (mCurMethodState->mDeferredCallEmitState != NULL) && (mCurMethodState->mDeferredCallEmitState->mCloseNode != NULL))
|
||||||
mCompiler->mPassInstance->MoreInfo("Error during deferred code emission", mCurMethodState->mDeferredCallEmitState->mCloseNode);
|
mCompiler->mPassInstance->MoreInfo("Error during deferred statement handling", mCurMethodState->mDeferredCallEmitState->mCloseNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bfError;
|
return bfError;
|
||||||
|
@ -12033,14 +12033,22 @@ void BfModule::CheckVariableDef(BfLocalVariable* variableDef)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinState)
|
BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinState, bool allowAcrossDeferredBlock)
|
||||||
{
|
{
|
||||||
bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin());
|
bool inMixinDecl = (mCurMethodInstance != NULL) && (mCurMethodInstance->IsMixin());
|
||||||
|
|
||||||
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(scopeName))
|
if (auto tokenNode = BfNodeDynCast<BfTokenNode>(scopeName))
|
||||||
{
|
{
|
||||||
if (tokenNode->GetToken() == BfToken_Colon)
|
if (tokenNode->GetToken() == BfToken_Colon)
|
||||||
|
{
|
||||||
|
if ((!allowAcrossDeferredBlock) && (mCurMethodState->mInDeferredBlock))
|
||||||
|
{
|
||||||
|
Fail("Cannot access method scope across deferred block boundary", scopeName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return &mCurMethodState->mHeadScope;
|
return &mCurMethodState->mHeadScope;
|
||||||
|
}
|
||||||
else if (tokenNode->GetToken() == BfToken_Mixin)
|
else if (tokenNode->GetToken() == BfToken_Mixin)
|
||||||
{
|
{
|
||||||
if (fromMixinState == NULL)
|
if (fromMixinState == NULL)
|
||||||
|
@ -12061,11 +12069,23 @@ BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinSt
|
||||||
{
|
{
|
||||||
auto findLabel = scopeName->ToString();
|
auto findLabel = scopeName->ToString();
|
||||||
|
|
||||||
|
bool crossedDeferredBlock = false;
|
||||||
|
|
||||||
auto checkScope = mCurMethodState->mCurScope;
|
auto checkScope = mCurMethodState->mCurScope;
|
||||||
while (checkScope != NULL)
|
while (checkScope != NULL)
|
||||||
{
|
{
|
||||||
|
if (checkScope->mIsDeferredBlock)
|
||||||
|
crossedDeferredBlock = true;
|
||||||
|
|
||||||
if (checkScope->mLabel == findLabel)
|
if (checkScope->mLabel == findLabel)
|
||||||
|
{
|
||||||
|
if ((crossedDeferredBlock) && (!allowAcrossDeferredBlock))
|
||||||
|
{
|
||||||
|
Fail(StrFormat("Cannot access scope '%s' across deferred block boundary", findLabel.c_str()), scopeName);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
return checkScope;
|
return checkScope;
|
||||||
|
}
|
||||||
checkScope = checkScope->mPrevScope;
|
checkScope = checkScope->mPrevScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12075,20 +12095,20 @@ BfScopeData* BfModule::FindScope(BfAstNode* scopeName, BfMixinState* fromMixinSt
|
||||||
|
|
||||||
if (auto scopeNode = BfNodeDynCast<BfScopeNode>(scopeName))
|
if (auto scopeNode = BfNodeDynCast<BfScopeNode>(scopeName))
|
||||||
{
|
{
|
||||||
return FindScope(scopeNode->mTargetNode);
|
return FindScope(scopeNode->mTargetNode, allowAcrossDeferredBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mCurMethodState->mCurScope;
|
return mCurMethodState->mCurScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfScopeData* BfModule::FindScope(BfAstNode* scopeName)
|
BfScopeData* BfModule::FindScope(BfAstNode* scopeName, bool allowAcrossDeferredBlock)
|
||||||
{
|
{
|
||||||
return FindScope(scopeName, mCurMethodState->mMixinState);
|
return FindScope(scopeName, mCurMethodState->mMixinState, allowAcrossDeferredBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
BfBreakData* BfModule::FindBreakData(BfAstNode* scopeName)
|
BfBreakData* BfModule::FindBreakData(BfAstNode* scopeName)
|
||||||
{
|
{
|
||||||
auto scopeData = FindScope(scopeName);
|
auto scopeData = FindScope(scopeName, false);
|
||||||
if (scopeData == NULL)
|
if (scopeData == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
int scopeDepth = scopeData->GetDepth();
|
int scopeDepth = scopeData->GetDepth();
|
||||||
|
@ -12097,6 +12117,8 @@ BfBreakData* BfModule::FindBreakData(BfAstNode* scopeName)
|
||||||
auto breakData = mCurMethodState->mBreakData;
|
auto breakData = mCurMethodState->mBreakData;
|
||||||
while ((breakData != NULL) && (scopeDepth < breakData->mScope->GetDepth()))
|
while ((breakData != NULL) && (scopeDepth < breakData->mScope->GetDepth()))
|
||||||
{
|
{
|
||||||
|
if (breakData->mScope->mIsConditional)
|
||||||
|
return NULL;
|
||||||
breakData = breakData->mPrevBreakData;
|
breakData = breakData->mPrevBreakData;
|
||||||
}
|
}
|
||||||
return breakData;
|
return breakData;
|
||||||
|
@ -12169,7 +12191,7 @@ void BfModule::EmitDeferredScopeCalls(bool useSrcPositions, BfScopeData* scopeDa
|
||||||
{
|
{
|
||||||
if (deferredCallEntry->mDeferredBlock != NULL)
|
if (deferredCallEntry->mDeferredBlock != NULL)
|
||||||
{
|
{
|
||||||
VisitChild(deferredCallEntry->mDeferredBlock);
|
VisitEmbeddedStatement(deferredCallEntry->mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
||||||
}
|
}
|
||||||
deferredCallEntry = deferredCallEntry->mNext;
|
deferredCallEntry = deferredCallEntry->mNext;
|
||||||
}
|
}
|
||||||
|
@ -12522,6 +12544,9 @@ void BfModule::EmitReturn(BfIRValue val)
|
||||||
|
|
||||||
void BfModule::EmitDefaultReturn()
|
void BfModule::EmitDefaultReturn()
|
||||||
{
|
{
|
||||||
|
if (mCurMethodState->mInDeferredBlock)
|
||||||
|
return;
|
||||||
|
|
||||||
if (mCurMethodState->mIRExitBlock)
|
if (mCurMethodState->mIRExitBlock)
|
||||||
{
|
{
|
||||||
EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
|
EmitDeferredScopeCalls(true, NULL, mCurMethodState->mIRExitBlock);
|
||||||
|
|
|
@ -107,6 +107,13 @@ enum BfProtectionCheckFlags
|
||||||
BfProtectionCheckFlag_AllowPrivate = 8,
|
BfProtectionCheckFlag_AllowPrivate = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BfEmbeddedStatementFlags
|
||||||
|
{
|
||||||
|
BfEmbeddedStatementFlags_None = 0,
|
||||||
|
BfEmbeddedStatementFlags_IsConditional = 1,
|
||||||
|
BfEmbeddedStatementFlags_IsDeferredBlock = 2
|
||||||
|
};
|
||||||
|
|
||||||
class BfLocalVariable
|
class BfLocalVariable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -299,7 +306,8 @@ public:
|
||||||
bool mInnerIsConditional;
|
bool mInnerIsConditional;
|
||||||
bool mHadOuterDynStack;
|
bool mHadOuterDynStack;
|
||||||
bool mAllowTargeting;
|
bool mAllowTargeting;
|
||||||
bool mHadScopeValueRetain;
|
bool mHadScopeValueRetain;
|
||||||
|
bool mIsDeferredBlock;
|
||||||
BfBlock* mAstBlock;
|
BfBlock* mAstBlock;
|
||||||
BfAstNode* mCloseNode;
|
BfAstNode* mCloseNode;
|
||||||
BfExprEvaluator* mExprEvaluator;
|
BfExprEvaluator* mExprEvaluator;
|
||||||
|
@ -329,6 +337,7 @@ public:
|
||||||
mInnerIsConditional = false;
|
mInnerIsConditional = false;
|
||||||
mHadOuterDynStack = false;
|
mHadOuterDynStack = false;
|
||||||
mHadScopeValueRetain = false;
|
mHadScopeValueRetain = false;
|
||||||
|
mIsDeferredBlock = false;
|
||||||
mAllowTargeting = true;
|
mAllowTargeting = true;
|
||||||
mMixinDepth = 0;
|
mMixinDepth = 0;
|
||||||
mScopeDepth = 0;
|
mScopeDepth = 0;
|
||||||
|
@ -870,12 +879,13 @@ public:
|
||||||
BfScopeData* mCurScope;
|
BfScopeData* mCurScope;
|
||||||
BfScopeData* mTailScope; // Usually equals mCurScope
|
BfScopeData* mTailScope; // Usually equals mCurScope
|
||||||
TempKind mTempKind; // Used for var inference, etc
|
TempKind mTempKind; // Used for var inference, etc
|
||||||
|
bool mInDeferredBlock;
|
||||||
bool mHadReturn;
|
bool mHadReturn;
|
||||||
bool mHadContinue;
|
bool mHadContinue;
|
||||||
bool mMayNeedThisAccessCheck;
|
bool mMayNeedThisAccessCheck;
|
||||||
bool mLeftBlockUncond; // Definitely left block. mHadReturn also sets mLeftBlock
|
bool mLeftBlockUncond; // Definitely left block. mHadReturn also sets mLeftBlock
|
||||||
bool mLeftBlockCond; // May have left block.
|
bool mLeftBlockCond; // May have left block.
|
||||||
bool mInPostReturn; // Unreachable code
|
bool mInPostReturn; // Unreachable code
|
||||||
bool mCrossingMixin; // ie: emitting dtors in response to a return in a mixin
|
bool mCrossingMixin; // ie: emitting dtors in response to a return in a mixin
|
||||||
bool mNoBind;
|
bool mNoBind;
|
||||||
bool mInConditionalBlock; // IE: RHS of ((A) && (B)), indicates an allocation in 'B' won't be dominated by a dtor, for example
|
bool mInConditionalBlock; // IE: RHS of ((A) && (B)), indicates an allocation in 'B' won't be dominated by a dtor, for example
|
||||||
|
@ -904,7 +914,7 @@ public:
|
||||||
mInHeadScope = true;
|
mInHeadScope = true;
|
||||||
mBreakData = NULL;
|
mBreakData = NULL;
|
||||||
mBlockNestLevel = 0;
|
mBlockNestLevel = 0;
|
||||||
mInPostReturn = false;
|
mInPostReturn = false;
|
||||||
mCrossingMixin = false;
|
mCrossingMixin = false;
|
||||||
mNoBind = false;
|
mNoBind = false;
|
||||||
mIsEmbedded = false;
|
mIsEmbedded = false;
|
||||||
|
@ -913,6 +923,7 @@ public:
|
||||||
mAllowUinitReads = false;
|
mAllowUinitReads = false;
|
||||||
mCancelledDeferredCall = false;
|
mCancelledDeferredCall = false;
|
||||||
mNoObjectAccessChecks = false;
|
mNoObjectAccessChecks = false;
|
||||||
|
mInDeferredBlock = false;
|
||||||
mDeferredLocalAssignData = NULL;
|
mDeferredLocalAssignData = NULL;
|
||||||
mCurLocalVarId = 0;
|
mCurLocalVarId = 0;
|
||||||
mCurAccessId = 1;
|
mCurAccessId = 1;
|
||||||
|
@ -1410,7 +1421,7 @@ public:
|
||||||
void ValueScopeEnd(BfIRValue valueScopeStart);
|
void ValueScopeEnd(BfIRValue valueScopeStart);
|
||||||
|
|
||||||
void AddBasicBlock(BfIRBlock bb, bool activate = true);
|
void AddBasicBlock(BfIRBlock bb, bool activate = true);
|
||||||
void VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator = NULL, bool isConditional = false);
|
void VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator = NULL, BfEmbeddedStatementFlags flags = BfEmbeddedStatementFlags_None);
|
||||||
void VisitCodeBlock(BfBlock* block);
|
void VisitCodeBlock(BfBlock* block);
|
||||||
void VisitCodeBlock(BfBlock* block, BfIRBlock continueBlock, BfIRBlock breakBlock, BfIRBlock fallthroughBlock, bool defaultBreak, bool* hadReturn = NULL, BfLabelNode* labelNode = NULL, bool closeScope = false);
|
void VisitCodeBlock(BfBlock* block, BfIRBlock continueBlock, BfIRBlock breakBlock, BfIRBlock fallthroughBlock, bool defaultBreak, bool* hadReturn = NULL, BfLabelNode* labelNode = NULL, bool closeScope = false);
|
||||||
void DoForLess(BfForEachStatement* forEachStmt);
|
void DoForLess(BfForEachStatement* forEachStmt);
|
||||||
|
@ -1594,8 +1605,8 @@ public:
|
||||||
BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfExprEvaluator* exprEvaluator = NULL);
|
BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfExprEvaluator* exprEvaluator = NULL);
|
||||||
BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfTypedValue val, bool updateSrcLoc = true, bool forceAddr = false);
|
BfLocalVariable* HandleVariableDeclaration(BfVariableDeclaration* varDecl, BfTypedValue val, bool updateSrcLoc = true, bool forceAddr = false);
|
||||||
void CheckVariableDef(BfLocalVariable* variableDef);
|
void CheckVariableDef(BfLocalVariable* variableDef);
|
||||||
BfScopeData* FindScope(BfAstNode* scopeName, BfMixinState* curMixinState);
|
BfScopeData* FindScope(BfAstNode* scopeName, BfMixinState* curMixinState, bool allowAcrossDeferredBlock);
|
||||||
BfScopeData* FindScope(BfAstNode* scopeName);
|
BfScopeData* FindScope(BfAstNode* scopeName, bool allowAcrossDeferredBlock);
|
||||||
BfBreakData* FindBreakData(BfAstNode* scopeName);
|
BfBreakData* FindBreakData(BfAstNode* scopeName);
|
||||||
void EmitLifetimeEnds(BfScopeData* scopeData);
|
void EmitLifetimeEnds(BfScopeData* scopeData);
|
||||||
void ClearLifetimeEnds();
|
void ClearLifetimeEnds();
|
||||||
|
|
|
@ -661,7 +661,8 @@ void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry)
|
||||||
}
|
}
|
||||||
AddLocalVariableDef(localVar, true);
|
AddLocalVariableDef(localVar, true);
|
||||||
}
|
}
|
||||||
VisitEmbeddedStatement(deferredCallEntry.mDeferredBlock);
|
|
||||||
|
VisitEmbeddedStatement(deferredCallEntry.mDeferredBlock, NULL, BfEmbeddedStatementFlags_IsDeferredBlock);
|
||||||
RestoreScopeState();
|
RestoreScopeState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2744,7 +2745,7 @@ void BfModule::AddBasicBlock(BfIRBlock bb, bool activate)
|
||||||
mBfIRBuilder->SetInsertPoint(bb);
|
mBfIRBuilder->SetInsertPoint(bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator, bool isConditional)
|
void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEvaluator, BfEmbeddedStatementFlags flags)
|
||||||
{
|
{
|
||||||
auto block = BfNodeDynCast<BfBlock>(stmt);
|
auto block = BfNodeDynCast<BfBlock>(stmt);
|
||||||
BfLabelNode* labelNode = NULL;
|
BfLabelNode* labelNode = NULL;
|
||||||
|
@ -2799,17 +2800,24 @@ void BfModule::VisitEmbeddedStatement(BfAstNode* stmt, BfExprEvaluator* exprEval
|
||||||
if (labelNode != NULL)
|
if (labelNode != NULL)
|
||||||
scopeData.mLabelNode = labelNode->mLabel;
|
scopeData.mLabelNode = labelNode->mLabel;
|
||||||
NewScopeState(block != NULL);
|
NewScopeState(block != NULL);
|
||||||
mCurMethodState->mCurScope->mOuterIsConditional = isConditional;
|
mCurMethodState->mCurScope->mOuterIsConditional = (flags & BfEmbeddedStatementFlags_IsConditional) != 0;
|
||||||
|
mCurMethodState->mCurScope->mIsDeferredBlock = (flags & BfEmbeddedStatementFlags_IsDeferredBlock) != 0;
|
||||||
mCurMethodState->mCurScope->mExprEvaluator = exprEvaluator;
|
mCurMethodState->mCurScope->mExprEvaluator = exprEvaluator;
|
||||||
if (block != NULL)
|
|
||||||
|
//
|
||||||
{
|
{
|
||||||
if (labelNode != NULL)
|
SetAndRestoreValue<bool> inDeferredBlock(mCurMethodState->mInDeferredBlock, mCurMethodState->mInDeferredBlock || mCurMethodState->mCurScope->mIsDeferredBlock);
|
||||||
VisitCodeBlock(block, BfIRBlock(), BfIRBlock(), BfIRBlock(), false, NULL, labelNode);
|
if (block != NULL)
|
||||||
|
{
|
||||||
|
if (labelNode != NULL)
|
||||||
|
VisitCodeBlock(block, BfIRBlock(), BfIRBlock(), BfIRBlock(), false, NULL, labelNode);
|
||||||
|
else
|
||||||
|
VisitCodeBlock(block);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
VisitCodeBlock(block);
|
VisitChild(stmt);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
VisitChild(stmt);
|
|
||||||
if ((block != NULL) && (closeBrace != NULL))
|
if ((block != NULL) && (closeBrace != NULL))
|
||||||
{
|
{
|
||||||
UpdateSrcPos(closeBrace);
|
UpdateSrcPos(closeBrace);
|
||||||
|
@ -2942,9 +2950,9 @@ void BfModule::VisitCodeBlock(BfBlock* block)
|
||||||
|
|
||||||
String* namePtr;
|
String* namePtr;
|
||||||
if (!mCurMethodState->mLocalMethodMap.TryAdd(localMethod->mMethodName, &namePtr, &localMethodPtr))
|
if (!mCurMethodState->mLocalMethodMap.TryAdd(localMethod->mMethodName, &namePtr, &localMethodPtr))
|
||||||
{
|
{
|
||||||
BF_ASSERT(localMethod->mNextWithSameName != *localMethodPtr);
|
BF_ASSERT(localMethod != *localMethodPtr);
|
||||||
localMethod->mNextWithSameName = *localMethodPtr;
|
localMethod->mNextWithSameName = *localMethodPtr;
|
||||||
}
|
}
|
||||||
*localMethodPtr = localMethod;
|
*localMethodPtr = localMethod;
|
||||||
}
|
}
|
||||||
|
@ -3334,7 +3342,7 @@ void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool i
|
||||||
falseDeferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
|
falseDeferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
|
||||||
SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &falseDeferredLocalAssignData);
|
SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &falseDeferredLocalAssignData);
|
||||||
if (includeFalseStmt)
|
if (includeFalseStmt)
|
||||||
VisitEmbeddedStatement(ifStmt->mFalseStatement, NULL, true);
|
VisitEmbeddedStatement(ifStmt->mFalseStatement, NULL, BfEmbeddedStatementFlags_IsConditional);
|
||||||
}
|
}
|
||||||
if ((!mCurMethodState->mLeftBlockUncond) && (!ignoredLastBlock))
|
if ((!mCurMethodState->mLeftBlockUncond) && (!ignoredLastBlock))
|
||||||
{
|
{
|
||||||
|
@ -4498,6 +4506,22 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
|
||||||
if (mCurMethodState->mClosureState != NULL)
|
if (mCurMethodState->mClosureState != NULL)
|
||||||
retType = mCurMethodState->mClosureState->mReturnType;
|
retType = mCurMethodState->mClosureState->mReturnType;
|
||||||
|
|
||||||
|
auto checkScope = mCurMethodState->mCurScope;
|
||||||
|
while (checkScope != NULL)
|
||||||
|
{
|
||||||
|
if (checkScope->mIsDeferredBlock)
|
||||||
|
{
|
||||||
|
Fail("Deferred blocks cannot contain 'return' statements", returnStmt);
|
||||||
|
if (returnStmt->mExpression != NULL)
|
||||||
|
{
|
||||||
|
BfExprEvaluator exprEvaluator(this);
|
||||||
|
CreateValueFromExpression(exprEvaluator, returnStmt->mExpression, GetPrimitiveType(BfTypeCode_Var), BfEvalExprFlags_None);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkScope = checkScope->mPrevScope;
|
||||||
|
}
|
||||||
|
|
||||||
if (retType == NULL)
|
if (retType == NULL)
|
||||||
{
|
{
|
||||||
if (returnStmt->mExpression != NULL)
|
if (returnStmt->mExpression != NULL)
|
||||||
|
@ -4616,7 +4640,7 @@ void BfModule::Visit(BfBreakStatement* breakStmt)
|
||||||
if (breakData->mIRBreakBlock)
|
if (breakData->mIRBreakBlock)
|
||||||
break;
|
break;
|
||||||
breakData = breakData->mPrevBreakData;
|
breakData = breakData->mPrevBreakData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((breakData == NULL) || (!breakData->mIRBreakBlock))
|
if ((breakData == NULL) || (!breakData->mIRBreakBlock))
|
||||||
|
@ -4630,6 +4654,22 @@ void BfModule::Visit(BfBreakStatement* breakStmt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mCurMethodState->mInDeferredBlock)
|
||||||
|
{
|
||||||
|
auto checkScope = mCurMethodState->mCurScope;
|
||||||
|
while (checkScope != NULL)
|
||||||
|
{
|
||||||
|
if (checkScope == breakData->mScope)
|
||||||
|
break;
|
||||||
|
if (checkScope->mIsDeferredBlock)
|
||||||
|
{
|
||||||
|
Fail("The break target crosses a deferred block boundary", breakStmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkScope = checkScope->mPrevScope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (HasDeferredScopeCalls(breakData->mScope))
|
if (HasDeferredScopeCalls(breakData->mScope))
|
||||||
{
|
{
|
||||||
EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRBreakBlock);
|
EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRBreakBlock);
|
||||||
|
@ -4724,6 +4764,22 @@ void BfModule::Visit(BfContinueStatement* continueStmt)
|
||||||
if (breakData->mInnerValueScopeStart)
|
if (breakData->mInnerValueScopeStart)
|
||||||
earliestValueScopeStart = breakData->mInnerValueScopeStart;
|
earliestValueScopeStart = breakData->mInnerValueScopeStart;
|
||||||
|
|
||||||
|
if (mCurMethodState->mInDeferredBlock)
|
||||||
|
{
|
||||||
|
auto checkScope = mCurMethodState->mCurScope;
|
||||||
|
while (checkScope != NULL)
|
||||||
|
{
|
||||||
|
if (checkScope == breakData->mScope)
|
||||||
|
break;
|
||||||
|
if (checkScope->mIsDeferredBlock)
|
||||||
|
{
|
||||||
|
Fail("The continue target crosses a deferred block boundary", continueStmt);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
checkScope = checkScope->mPrevScope;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((nextScope != NULL) && (HasDeferredScopeCalls(nextScope)))
|
if ((nextScope != NULL) && (HasDeferredScopeCalls(nextScope)))
|
||||||
{
|
{
|
||||||
EmitDeferredScopeCalls(true, nextScope, breakData->mIRContinueBlock);
|
EmitDeferredScopeCalls(true, nextScope, breakData->mIRContinueBlock);
|
||||||
|
@ -6021,7 +6077,7 @@ void BfModule::Visit(BfDeferStatement* deferStmt)
|
||||||
scope = &mCurMethodState->mHeadScope;
|
scope = &mCurMethodState->mHeadScope;
|
||||||
}
|
}
|
||||||
else if (deferStmt->mScopeName != NULL)
|
else if (deferStmt->mScopeName != NULL)
|
||||||
scope = FindScope(deferStmt->mScopeName);
|
scope = FindScope(deferStmt->mScopeName, true);
|
||||||
else
|
else
|
||||||
scope = mCurMethodState->mCurScope;
|
scope = mCurMethodState->mCurScope;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue