mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 12:32:20 +02:00
Fixed issue with multiple Dispose calls on foreach enumerator
This commit is contained in:
parent
9236b3e0d2
commit
85462e6d62
2 changed files with 60 additions and 8 deletions
|
@ -5889,7 +5889,7 @@ void BfModule::DoForLess(BfForEachStatement* forEachStmt)
|
|||
}
|
||||
|
||||
void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||
{
|
||||
{
|
||||
if ((forEachStmt->mInToken != NULL) &&
|
||||
((forEachStmt->mInToken->GetToken() == BfToken_LChevron) || (forEachStmt->mInToken->GetToken() == BfToken_LessEquals)))
|
||||
{
|
||||
|
@ -5900,7 +5900,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
auto autoComplete = mCompiler->GetAutoComplete();
|
||||
UpdateSrcPos(forEachStmt);
|
||||
|
||||
BfScopeData scopeData;
|
||||
BfScopeData scopeData;
|
||||
// We set mIsLoop after the non-looped initializations
|
||||
if (forEachStmt->mLabelNode != NULL)
|
||||
scopeData.mLabelNode = forEachStmt->mLabelNode->mLabel;
|
||||
|
@ -6287,7 +6287,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
localDef->mAddr = itr.mValue;
|
||||
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||
localDef->mReadFromId = 0;
|
||||
localDef->Init();
|
||||
localDef->Init();
|
||||
UpdateSrcPos(forEachStmt);
|
||||
CheckVariableDef(localDef);
|
||||
AddLocalVariableDef(localDef, true);
|
||||
|
@ -6400,7 +6400,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
varTypedVal = BfTypedValue(varInst, varType, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Iterator
|
||||
if (itr)
|
||||
{
|
||||
|
@ -6422,9 +6422,13 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
AddDeferredCall(moduleMethodInstance, functionBindResult.mIRArgs, mCurMethodState->mCurScope);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
scopeData.mIsLoop = true;
|
||||
BfScopeData innerScopeData;
|
||||
innerScopeData.mValueScopeStart = ValueScopeStart();
|
||||
mCurMethodState->AddScope(&innerScopeData);
|
||||
NewScopeState(true, false);
|
||||
innerScopeData.mIsLoop = true;
|
||||
|
||||
if ((autoComplete != NULL) && (forEachStmt->mVariableTypeRef != NULL))
|
||||
autoComplete->CheckVarResolution(forEachStmt->mVariableTypeRef, varType);
|
||||
|
@ -6432,7 +6436,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
if (isArray || isSizedArray)
|
||||
mBfIRBuilder->CreateStore(GetConstValue(0), itr.mValue);
|
||||
|
||||
auto valueScopeStartInner = ValueScopeStart();
|
||||
auto valueScopeStartInner = ValueScopeStart();
|
||||
|
||||
// We may have a call in the loop body
|
||||
mCurMethodState->mMayNeedThisAccessCheck = true;
|
||||
|
@ -6445,7 +6449,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
BfBreakData breakData;
|
||||
breakData.mIRContinueBlock = incBB;
|
||||
breakData.mIRBreakBlock = endBB;
|
||||
breakData.mScope = &scopeData;
|
||||
breakData.mScope = &innerScopeData;
|
||||
breakData.mInnerValueScopeStart = valueScopeStartInner;
|
||||
breakData.mPrevBreakData = mCurMethodState->mBreakData;
|
||||
SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
|
||||
|
@ -6679,6 +6683,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
|||
mCurMethodState->mLeftBlockCond = false;
|
||||
|
||||
RestoreScopeState();
|
||||
RestoreScopeState();
|
||||
}
|
||||
|
||||
void BfModule::Visit(BfDeferStatement* deferStmt)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma warning disable 168
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
|
||||
namespace Tests
|
||||
{
|
||||
|
@ -12,6 +13,21 @@ namespace Tests
|
|||
public int32 mB;
|
||||
}
|
||||
|
||||
class EnumeratorTest : IEnumerator<int32>, IDisposable
|
||||
{
|
||||
public int mDispCount;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
mDispCount++;
|
||||
}
|
||||
|
||||
public Result<int32> GetNext()
|
||||
{
|
||||
return .Err;
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -26,6 +42,37 @@ namespace Tests
|
|||
StructA sa = val;
|
||||
int idx = @val;
|
||||
}
|
||||
|
||||
var e = scope EnumeratorTest();
|
||||
for (var val in e)
|
||||
{
|
||||
}
|
||||
Test.Assert(e.mDispCount == 1);
|
||||
for (var val in e)
|
||||
{
|
||||
break;
|
||||
}
|
||||
Test.Assert(e.mDispCount == 2);
|
||||
TestEnumerator1(e);
|
||||
Test.Assert(e.mDispCount == 3);
|
||||
TestEnumerator2(e);
|
||||
Test.Assert(e.mDispCount == 4);
|
||||
}
|
||||
|
||||
public static void TestEnumerator1(EnumeratorTest e)
|
||||
{
|
||||
for (var val in e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public static void TestEnumerator2(EnumeratorTest e)
|
||||
{
|
||||
for (var val in e)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue