mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Improvements to unassigned variable detection
This commit is contained in:
parent
da563ee14b
commit
5b8d2ffee2
6 changed files with 283 additions and 134 deletions
|
@ -3103,6 +3103,7 @@ namespace System {
|
||||||
AdjustmentRule [] adjustmentRules,
|
AdjustmentRule [] adjustmentRules,
|
||||||
out bool adjustmentRulesSupportDst) {
|
out bool adjustmentRulesSupportDst) {
|
||||||
|
|
||||||
|
adjustmentRulesSupportDst = false;
|
||||||
if (id.IsNull) {
|
if (id.IsNull) {
|
||||||
//throw new ArgumentNullException("id");
|
//throw new ArgumentNullException("id");
|
||||||
return .Err;
|
return .Err;
|
||||||
|
@ -3125,8 +3126,6 @@ namespace System {
|
||||||
}
|
}
|
||||||
Contract.EndContractBlock();
|
Contract.EndContractBlock();
|
||||||
|
|
||||||
adjustmentRulesSupportDst = false;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// "adjustmentRules" can either be null or a valid array of AdjustmentRule objects.
|
// "adjustmentRules" can either be null or a valid array of AdjustmentRule objects.
|
||||||
// A valid array is one that does not contain any null elements and all elements
|
// A valid array is one that does not contain any null elements and all elements
|
||||||
|
|
|
@ -6,6 +6,45 @@ namespace IDETest
|
||||||
{
|
{
|
||||||
class LocalVars
|
class LocalVars
|
||||||
{
|
{
|
||||||
|
public void If1()
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b = 123;
|
||||||
|
if (b == 234)
|
||||||
|
{
|
||||||
|
a = 234;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
b = a; //FAIL
|
||||||
|
}
|
||||||
|
|
||||||
|
public void If2(out int a) //FAIL
|
||||||
|
{
|
||||||
|
int b = 123;
|
||||||
|
if (b == 234)
|
||||||
|
return;
|
||||||
|
a = 234;
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void For1(out int a) //FAIL
|
||||||
|
{
|
||||||
|
for (int b < 2)
|
||||||
|
a = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Do1(out int a) //FAIL
|
||||||
|
{
|
||||||
|
int b = 123;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (b == 234)
|
||||||
|
break;
|
||||||
|
a = 9;
|
||||||
|
}
|
||||||
|
b = a;
|
||||||
|
}
|
||||||
|
|
||||||
public void Switch1()
|
public void Switch1()
|
||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
|
@ -91,6 +130,20 @@ namespace IDETest
|
||||||
int c = b;
|
int c = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Switch6()
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
|
||||||
|
Result<int> iResult = .Ok(123);
|
||||||
|
switch (iResult)
|
||||||
|
{
|
||||||
|
case .Ok(out val):
|
||||||
|
case .Err: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int a = val; //FAIL
|
||||||
|
}
|
||||||
|
|
||||||
public void While1()
|
public void While1()
|
||||||
{
|
{
|
||||||
int a = 1;
|
int a = 1;
|
||||||
|
|
|
@ -6553,7 +6553,7 @@ BfTypedValue BfExprEvaluator::ResolveArgValue(BfResolvedArg& resolvedArg, BfType
|
||||||
localVar->mIsReadOnly = isLet;
|
localVar->mIsReadOnly = isLet;
|
||||||
localVar->mReadFromId = 0;
|
localVar->mReadFromId = 0;
|
||||||
localVar->mWrittenToId = 0;
|
localVar->mWrittenToId = 0;
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
mModule->CheckVariableDef(localVar);
|
mModule->CheckVariableDef(localVar);
|
||||||
localVar->Init();
|
localVar->Init();
|
||||||
mModule->AddLocalVariableDef(localVar, true);
|
mModule->AddLocalVariableDef(localVar, true);
|
||||||
|
@ -10940,7 +10940,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
|
||||||
methodDef->mParams.push_back(paramDef);
|
methodDef->mParams.push_back(paramDef);
|
||||||
|
|
||||||
localVar->mResolvedType = invokeMethodInstance->GetParamType(paramIdx);
|
localVar->mResolvedType = invokeMethodInstance->GetParamType(paramIdx);
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localVar->mReadFromId = 0;
|
localVar->mReadFromId = 0;
|
||||||
|
|
||||||
auto rootMethodState = methodState.GetRootMethodState();
|
auto rootMethodState = methodState.GetRootMethodState();
|
||||||
|
@ -13920,17 +13920,17 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
mModule->AddLocalVariableDef(newLocalVar, hasConstValue);
|
mModule->AddLocalVariableDef(newLocalVar, hasConstValue);
|
||||||
auto inLocalVar = exprEvaluator->mResultLocalVar;
|
auto inLocalVar = exprEvaluator->mResultLocalVar;
|
||||||
|
|
||||||
newLocalVar->mIsAssigned = inLocalVar->mIsAssigned;
|
newLocalVar->mAssignedKind = inLocalVar->mAssignedKind;
|
||||||
newLocalVar->mUnassignedFieldFlags = inLocalVar->mUnassignedFieldFlags;
|
newLocalVar->mUnassignedFieldFlags = inLocalVar->mUnassignedFieldFlags;
|
||||||
newLocalVar->mReadFromId = inLocalVar->mReadFromId;
|
newLocalVar->mReadFromId = inLocalVar->mReadFromId;
|
||||||
newLocalVar->mIsReadOnly = inLocalVar->mIsReadOnly;
|
newLocalVar->mIsReadOnly = inLocalVar->mIsReadOnly;
|
||||||
|
|
||||||
if ((!newLocalVar->mIsAssigned) && (mModule->mCurMethodState->mDeferredLocalAssignData != NULL))
|
if ((newLocalVar->mAssignedKind == BfLocalVarAssignKind_None) && (mModule->mCurMethodState->mDeferredLocalAssignData != NULL))
|
||||||
{
|
{
|
||||||
for (auto deferredAssign : mModule->mCurMethodState->mDeferredLocalAssignData->mAssignedLocals)
|
for (auto deferredAssign : mModule->mCurMethodState->mDeferredLocalAssignData->mAssignedLocals)
|
||||||
{
|
{
|
||||||
if (deferredAssign.mLocalVar == inLocalVar)
|
if (deferredAssign.mLocalVar == inLocalVar)
|
||||||
newLocalVar->mIsAssigned = true;
|
newLocalVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14095,7 +14095,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
argValue = target;
|
argValue = target;
|
||||||
localVar->mName = "this";
|
localVar->mName = "this";
|
||||||
localVar->mIsThis = true;
|
localVar->mIsThis = true;
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -14123,7 +14123,7 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
auto refType = (BfRefType*)localVar->mResolvedType;
|
auto refType = (BfRefType*)localVar->mResolvedType;
|
||||||
localVar->mAddr = mModule->LoadValue(argValue).mValue;
|
localVar->mAddr = mModule->LoadValue(argValue).mValue;
|
||||||
localVar->mResolvedType = argValue.mType->GetUnderlyingType();
|
localVar->mResolvedType = argValue.mType->GetUnderlyingType();
|
||||||
localVar->mIsAssigned = refType->mRefKind != BfRefType::RefKind_Out;
|
localVar->mAssignedKind = (refType->mRefKind != BfRefType::RefKind_Out) ? BfLocalVarAssignKind_Unconditional : BfLocalVarAssignKind_None;
|
||||||
}
|
}
|
||||||
else if (argValue.IsAddr())
|
else if (argValue.IsAddr())
|
||||||
localVar->mAddr = argValue.mValue;
|
localVar->mAddr = argValue.mValue;
|
||||||
|
@ -14202,8 +14202,8 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
if (mResultLocalVar != NULL)
|
if (mResultLocalVar != NULL)
|
||||||
{
|
{
|
||||||
auto inLocalVar = mResultLocalVar;
|
auto inLocalVar = mResultLocalVar;
|
||||||
if (localVar->mIsAssigned)
|
if (localVar->mAssignedKind != BfLocalVarAssignKind_None)
|
||||||
inLocalVar->mIsAssigned = true;
|
inLocalVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
if (localVar->mReadFromId != -1)
|
if (localVar->mReadFromId != -1)
|
||||||
inLocalVar->mReadFromId = mModule->mCurMethodState->GetRootMethodState()->mCurAccessId++;
|
inLocalVar->mReadFromId = mModule->mCurMethodState->GetRootMethodState()->mCurAccessId++;
|
||||||
}
|
}
|
||||||
|
@ -14220,8 +14220,8 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
if ((exprEvaluator != NULL) && (exprEvaluator->mResultLocalVar != NULL))
|
if ((exprEvaluator != NULL) && (exprEvaluator->mResultLocalVar != NULL))
|
||||||
{
|
{
|
||||||
auto inLocalVar = exprEvaluator->mResultLocalVar;
|
auto inLocalVar = exprEvaluator->mResultLocalVar;
|
||||||
if (localVar->mIsAssigned)
|
if (localVar->mAssignedKind != BfLocalVarAssignKind_None)
|
||||||
inLocalVar->mIsAssigned = true;
|
inLocalVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
if (localVar->mReadFromId != -1)
|
if (localVar->mReadFromId != -1)
|
||||||
inLocalVar->mReadFromId = mModule->mCurMethodState->GetRootMethodState()->mCurAccessId++;
|
inLocalVar->mReadFromId = mModule->mCurMethodState->GetRootMethodState()->mCurAccessId++;
|
||||||
}
|
}
|
||||||
|
@ -15478,12 +15478,12 @@ void BfExprEvaluator::CheckResultForReading(BfTypedValue& typedValue)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!localVar->mIsAssigned)
|
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
{
|
{
|
||||||
mModule->TryLocalVariableInit(localVar);
|
mModule->TryLocalVariableInit(localVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!localVar->mIsAssigned)
|
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
{
|
{
|
||||||
auto methodStateForLocal = mModule->mCurMethodState->GetMethodStateForLocal(localVar);
|
auto methodStateForLocal = mModule->mCurMethodState->GetMethodStateForLocal(localVar);
|
||||||
|
|
||||||
|
@ -15500,7 +15500,7 @@ void BfExprEvaluator::CheckResultForReading(BfTypedValue& typedValue)
|
||||||
auto assignedLocal = assignedVar.mLocalVar;
|
auto assignedLocal = assignedVar.mLocalVar;
|
||||||
if (assignedLocal == localVar)
|
if (assignedLocal == localVar)
|
||||||
{
|
{
|
||||||
int assignedFieldIdx = (assignedVar.mLocalVarField) - 1;
|
int assignedFieldIdx = assignedVar.mLocalVarField;
|
||||||
if (assignedFieldIdx >= 0)
|
if (assignedFieldIdx >= 0)
|
||||||
undefinedFieldFlags &= ~((int64)1 << assignedFieldIdx);
|
undefinedFieldFlags &= ~((int64)1 << assignedFieldIdx);
|
||||||
else
|
else
|
||||||
|
|
|
@ -40,11 +40,11 @@ void BfLocalVariable::Init()
|
||||||
{
|
{
|
||||||
if (mResolvedType->IsValuelessType())
|
if (mResolvedType->IsValuelessType())
|
||||||
{
|
{
|
||||||
mIsAssigned = true;
|
mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mIsAssigned)
|
if (mAssignedKind != BfLocalVarAssignKind_None)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool isStruct = mResolvedType->IsStruct();
|
bool isStruct = mResolvedType->IsStruct();
|
||||||
|
@ -64,7 +64,7 @@ void BfLocalVariable::Init()
|
||||||
mUnassignedFieldFlags &= ~(((int64)1 << typeInstance->mBaseType->mMergedFieldDataCount) - 1);
|
mUnassignedFieldFlags &= ~(((int64)1 << typeInstance->mBaseType->mMergedFieldDataCount) - 1);
|
||||||
}
|
}
|
||||||
if (mUnassignedFieldFlags == 0)
|
if (mUnassignedFieldFlags == 0)
|
||||||
mIsAssigned = true;
|
mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -117,20 +117,39 @@ void BfDeferredLocalAssignData::SetIntersection(const BfDeferredLocalAssignData&
|
||||||
{
|
{
|
||||||
BreakExtendChain();
|
BreakExtendChain();
|
||||||
|
|
||||||
//TODO: We got rid of this case because we now set the proper assigned data when we do a return
|
|
||||||
// If one of these had a return then treat that case as if it did have an assign -- because it doesn't
|
|
||||||
// cause an UNASSIGNED value to be used
|
|
||||||
// if (mHadReturn || otherLocalAssignData.mHadReturn)
|
|
||||||
// {
|
|
||||||
// SetUnion(otherLocalAssignData);
|
|
||||||
// mHadFallthrough = mHadFallthrough && otherLocalAssignData.mHadFallthrough;
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (int i = 0; i < (int)mAssignedLocals.size(); )
|
for (int i = 0; i < (int)mAssignedLocals.size(); )
|
||||||
{
|
{
|
||||||
auto& local = mAssignedLocals[i];
|
auto& local = mAssignedLocals[i];
|
||||||
if (!otherLocalAssignData.mAssignedLocals.Contains(local))
|
|
||||||
|
bool wantRemove = true;
|
||||||
|
bool foundOtherFields = false;
|
||||||
|
for (auto& otherLocalAssignData : otherLocalAssignData.mAssignedLocals)
|
||||||
|
{
|
||||||
|
if (otherLocalAssignData.mLocalVar == local.mLocalVar)
|
||||||
|
{
|
||||||
|
if ((otherLocalAssignData.mLocalVarField == local.mLocalVarField) || (otherLocalAssignData.mLocalVarField == -1))
|
||||||
|
{
|
||||||
|
if (otherLocalAssignData.mAssignKind == BfLocalVarAssignKind_Conditional)
|
||||||
|
local.mAssignKind = BfLocalVarAssignKind_Conditional;
|
||||||
|
wantRemove = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
foundOtherFields = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((wantRemove) && (foundOtherFields))
|
||||||
|
{
|
||||||
|
for (auto& otherLocalAssignData : otherLocalAssignData.mAssignedLocals)
|
||||||
|
{
|
||||||
|
if (otherLocalAssignData.mLocalVar == local.mLocalVar)
|
||||||
|
{
|
||||||
|
mAssignedLocals.Add(otherLocalAssignData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantRemove)
|
||||||
{
|
{
|
||||||
mAssignedLocals.RemoveAt(i);
|
mAssignedLocals.RemoveAt(i);
|
||||||
}
|
}
|
||||||
|
@ -175,7 +194,7 @@ BfMethodState::~BfMethodState()
|
||||||
BF_ASSERT(mCurAccessId == 1);
|
BF_ASSERT(mCurAccessId == 1);
|
||||||
BF_ASSERT(mCurLocalVarId <= 0);
|
BF_ASSERT(mCurLocalVarId <= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto local : mLocals)
|
for (auto local : mLocals)
|
||||||
delete local;
|
delete local;
|
||||||
|
|
||||||
|
@ -198,7 +217,7 @@ BfMethodState* BfMethodState::GetMethodStateForLocal(BfLocalVariable* localVar)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx)
|
void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx, BfLocalVarAssignKind assignKind, bool isFromDeferredAssignData)
|
||||||
{
|
{
|
||||||
auto localVarMethodState = GetMethodStateForLocal(localVar);
|
auto localVarMethodState = GetMethodStateForLocal(localVar);
|
||||||
if (localVarMethodState != this)
|
if (localVarMethodState != this)
|
||||||
|
@ -207,7 +226,13 @@ void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx)
|
||||||
}
|
}
|
||||||
//BF_ASSERT(localVarMethodState == this);
|
//BF_ASSERT(localVarMethodState == this);
|
||||||
|
|
||||||
if (!localVar->mIsAssigned)
|
// if (assignKind == BfLocalVarAssignKind_None)
|
||||||
|
// assignKind = ((localVarMethodState->mLeftBlockCond) && ((mDeferredLocalAssignData != NULL) || isFromDeferredAssignData)) ? BfLocalVarAssignKind_Conditional : BfLocalVarAssignKind_Unconditional;
|
||||||
|
//
|
||||||
|
// //assignKind = BfLocalVarAssignKind_Unconditional;
|
||||||
|
|
||||||
|
|
||||||
|
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
{
|
{
|
||||||
BfDeferredLocalAssignData* ifDeferredLocalAssignData = NULL;
|
BfDeferredLocalAssignData* ifDeferredLocalAssignData = NULL;
|
||||||
|
|
||||||
|
@ -226,7 +251,14 @@ void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx)
|
||||||
((deferredLocalAssignData->mIsChained) || (deferredLocalAssignData->mIsUnconditional)))
|
((deferredLocalAssignData->mIsChained) || (deferredLocalAssignData->mIsUnconditional)))
|
||||||
deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
|
deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
|
||||||
|
|
||||||
if ((deferredLocalAssignData == NULL) || (localVar->mLocalVarId >= deferredLocalAssignData->mVarIdBarrier))
|
if (assignKind == BfLocalVarAssignKind_None)
|
||||||
|
assignKind = ((deferredLocalAssignData != NULL) && (deferredLocalAssignData->mLeftBlock)) ? BfLocalVarAssignKind_Conditional : BfLocalVarAssignKind_Unconditional;
|
||||||
|
|
||||||
|
if (localVar->mAssignedKind == assignKind)
|
||||||
|
{
|
||||||
|
// Leave it alone
|
||||||
|
}
|
||||||
|
else if ((deferredLocalAssignData == NULL) || (localVar->mLocalVarId >= deferredLocalAssignData->mVarIdBarrier))
|
||||||
{
|
{
|
||||||
if (fieldIdx >= 0)
|
if (fieldIdx >= 0)
|
||||||
{
|
{
|
||||||
|
@ -236,18 +268,21 @@ void BfMethodState::LocalDefined(BfLocalVariable* localVar, int fieldIdx)
|
||||||
|
|
||||||
}*/
|
}*/
|
||||||
if (localVar->mUnassignedFieldFlags == 0)
|
if (localVar->mUnassignedFieldFlags == 0)
|
||||||
localVar->mIsAssigned = true;
|
{
|
||||||
|
if (localVar->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
|
localVar->mAssignedKind = assignKind;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = assignKind;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BF_ASSERT(deferredLocalAssignData->mVarIdBarrier != -1);
|
BF_ASSERT(deferredLocalAssignData->mVarIdBarrier != -1);
|
||||||
|
|
||||||
BfAssignedLocal defineVal = {localVar, fieldIdx + 1};
|
BfAssignedLocal defineVal = {localVar, fieldIdx, assignKind};
|
||||||
auto& assignedLocals = deferredLocalAssignData->mAssignedLocals;
|
auto& assignedLocals = deferredLocalAssignData->mAssignedLocals;
|
||||||
if (!assignedLocals.Contains(defineVal))
|
if (!assignedLocals.Contains(defineVal))
|
||||||
assignedLocals.push_back(defineVal);
|
assignedLocals.push_back(defineVal);
|
||||||
|
@ -269,7 +304,7 @@ void BfMethodState::ApplyDeferredLocalAssignData(const BfDeferredLocalAssignData
|
||||||
|
|
||||||
for (auto& assignedLocal : deferredLocalAssignData.mAssignedLocals)
|
for (auto& assignedLocal : deferredLocalAssignData.mAssignedLocals)
|
||||||
{
|
{
|
||||||
LocalDefined(assignedLocal.mLocalVar);
|
LocalDefined(assignedLocal.mLocalVar, assignedLocal.mLocalVarField, assignedLocal.mAssignKind, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2029,14 +2064,14 @@ bool BfModule::TryLocalVariableInit(BfLocalVariable* localVar)
|
||||||
|
|
||||||
localVar->mUnassignedFieldFlags &= ~checkMask;
|
localVar->mUnassignedFieldFlags &= ~checkMask;
|
||||||
if (localVar->mUnassignedFieldFlags == 0)
|
if (localVar->mUnassignedFieldFlags == 0)
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
checkTypeInstance = checkTypeInstance->mBaseType;
|
checkTypeInstance = checkTypeInstance->mBaseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return localVar->mIsAssigned;
|
return localVar->mAssignedKind != BfLocalVarAssignKind_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
|
void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
|
||||||
|
@ -2069,7 +2104,7 @@ void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
|
||||||
|
|
||||||
if ((localVar->mReadFromId == -1) || (isOut) || ((localVar->mIsThis) && (mCurTypeInstance->IsStruct())))
|
if ((localVar->mReadFromId == -1) || (isOut) || ((localVar->mIsThis) && (mCurTypeInstance->IsStruct())))
|
||||||
{
|
{
|
||||||
if ((!localVar->mIsAssigned) & (localVar->IsParam()))
|
if ((localVar->mAssignedKind != BfLocalVarAssignKind_Unconditional) & (localVar->IsParam()))
|
||||||
TryLocalVariableInit(localVar);
|
TryLocalVariableInit(localVar);
|
||||||
|
|
||||||
// We may skip processing of local methods, so we won't know if it bind to any of our local variables or not
|
// We may skip processing of local methods, so we won't know if it bind to any of our local variables or not
|
||||||
|
@ -2077,7 +2112,8 @@ void BfModule::LocalVariableDone(BfLocalVariable* localVar, bool isMethodExit)
|
||||||
//bool deferFullAnalysis = true;
|
//bool deferFullAnalysis = true;
|
||||||
bool deferUsageWarning = deferFullAnalysis && mCompiler->IsAutocomplete();
|
bool deferUsageWarning = deferFullAnalysis && mCompiler->IsAutocomplete();
|
||||||
|
|
||||||
if ((!localVar->mIsAssigned) && (!localVar->mIsImplicitParam))
|
if (((localVar->mAssignedKind != BfLocalVarAssignKind_Unconditional) || (localVar->mHadExitBeforeAssign)) &&
|
||||||
|
(!localVar->mIsImplicitParam))
|
||||||
{
|
{
|
||||||
if (deferUsageWarning)
|
if (deferUsageWarning)
|
||||||
{
|
{
|
||||||
|
@ -4022,7 +4058,7 @@ void BfModule::CreateDynamicCastMethod()
|
||||||
auto trueBB = mBfIRBuilder->CreateBlock("check.true");
|
auto trueBB = mBfIRBuilder->CreateBlock("check.true");
|
||||||
//auto falseBB = mBfIRBuilder->CreateBlock("check.false");
|
//auto falseBB = mBfIRBuilder->CreateBlock("check.false");
|
||||||
auto exitBB = mBfIRBuilder->CreateBlock("exit");
|
auto exitBB = mBfIRBuilder->CreateBlock("exit");
|
||||||
|
|
||||||
SizedArray<int, 8> typeMatches;
|
SizedArray<int, 8> typeMatches;
|
||||||
SizedArray<BfTypeInstance*, 8> exChecks;
|
SizedArray<BfTypeInstance*, 8> exChecks;
|
||||||
FindSubTypes(mCurTypeInstance, &typeMatches, &exChecks, isInterfacePass);
|
FindSubTypes(mCurTypeInstance, &typeMatches, &exChecks, isInterfacePass);
|
||||||
|
@ -4036,7 +4072,7 @@ void BfModule::CreateDynamicCastMethod()
|
||||||
genericArgs.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
|
genericArgs.push_back(GetGenericParamType(BfGenericParamKind_Type, i));
|
||||||
auto unboundType = ResolveTypeDef(mCurTypeInstance->mTypeDef, genericArgs, BfPopulateType_Declaration);
|
auto unboundType = ResolveTypeDef(mCurTypeInstance->mTypeDef, genericArgs, BfPopulateType_Declaration);
|
||||||
typeMatches.push_back(unboundType->mTypeId);
|
typeMatches.push_back(unboundType->mTypeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mCurTypeInstance->IsBoxed())
|
if (mCurTypeInstance->IsBoxed())
|
||||||
{
|
{
|
||||||
|
@ -13266,7 +13302,7 @@ BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, boo
|
||||||
if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL))
|
if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL))
|
||||||
mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
|
mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return localVarDef;
|
return localVarDef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13851,20 +13887,27 @@ void BfModule::MarkScopeLeft(BfScopeData* scopeData)
|
||||||
deferredLocalAssignData->mIsUnconditional = false;
|
deferredLocalAssignData->mIsUnconditional = false;
|
||||||
deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
|
deferredLocalAssignData = deferredLocalAssignData->mChainedAssignData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//for (int localIdx = scopeData->mLocalVarStart; localIdx < (int)mCurMethodState->mLocals.size(); localIdx++)
|
// When we leave a scope, mark those as assigned for deferred assignment purposes
|
||||||
|
for (int localIdx = scopeData->mLocalVarStart; localIdx < (int)mCurMethodState->mLocals.size(); localIdx++)
|
||||||
// We mark all unassigned variables as assigned now, for avoiding "may be unassigned" usage cases like:
|
|
||||||
// int b;
|
|
||||||
// if (cond) return;
|
|
||||||
// else b = 1;
|
|
||||||
// Use(b);
|
|
||||||
for (int localIdx = 0; localIdx < (int)mCurMethodState->mLocals.size(); localIdx++)
|
|
||||||
{
|
{
|
||||||
auto localDef = mCurMethodState->mLocals[localIdx];
|
auto localDef = mCurMethodState->mLocals[localIdx];
|
||||||
if ((!localDef->mIsAssigned) && (!localDef->IsParam()))
|
if (localDef->mAssignedKind == BfLocalVarAssignKind_None)
|
||||||
|
{
|
||||||
|
bool hadAssignment = false;
|
||||||
|
if (mCurMethodState->mDeferredLocalAssignData != NULL)
|
||||||
|
{
|
||||||
|
for (auto& entry : mCurMethodState->mDeferredLocalAssignData->mAssignedLocals)
|
||||||
|
if (entry.mLocalVar == localDef)
|
||||||
|
hadAssignment = true;
|
||||||
|
}
|
||||||
|
if (!hadAssignment)
|
||||||
|
localDef->mHadExitBeforeAssign = true;
|
||||||
mCurMethodState->LocalDefined(localDef);
|
mCurMethodState->LocalDefined(localDef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14843,7 +14886,7 @@ void BfModule::EmitDtorBody()
|
||||||
localDef->mName = "_";
|
localDef->mName = "_";
|
||||||
localDef->mResolvedType = fieldType;
|
localDef->mResolvedType = fieldType;
|
||||||
localDef->mAddr = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(fieldType));
|
localDef->mAddr = mBfIRBuilder->CreateAlloca(mBfIRBuilder->MapType(fieldType));
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
AddLocalVariableDef(localDef);
|
AddLocalVariableDef(localDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15591,7 +15634,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
if (thisVariable != NULL)
|
if (thisVariable != NULL)
|
||||||
{
|
{
|
||||||
thisVariable->mUnassignedFieldFlags = 0;
|
thisVariable->mUnassignedFieldFlags = 0;
|
||||||
thisVariable->mIsAssigned = true;
|
thisVariable->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16142,11 +16185,11 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
|
||||||
paramVar->mParamIdx = -1;
|
paramVar->mParamIdx = -1;
|
||||||
if ((methodDef->mMethodType == BfMethodType_Ctor) && (mCurTypeInstance->IsStruct()))
|
if ((methodDef->mMethodType == BfMethodType_Ctor) && (mCurTypeInstance->IsStruct()))
|
||||||
{
|
{
|
||||||
paramVar->mIsAssigned = false;
|
paramVar->mAssignedKind = BfLocalVarAssignKind_None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paramVar->mIsAssigned = true;
|
paramVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
|
|
||||||
paramVar->mReadFromId = -1;
|
paramVar->mReadFromId = -1;
|
||||||
|
@ -16242,11 +16285,11 @@ void BfModule::ProcessMethod_SetupParams(BfMethodInstance* methodInstance, BfTyp
|
||||||
if (resolvedType->IsRef())
|
if (resolvedType->IsRef())
|
||||||
{
|
{
|
||||||
auto refType = (BfRefType*)resolvedType;
|
auto refType = (BfRefType*)resolvedType;
|
||||||
paramVar->mIsAssigned = refType->mRefKind != BfRefType::RefKind_Out;
|
paramVar->mAssignedKind = (refType->mRefKind != BfRefType::RefKind_Out) ? BfLocalVarAssignKind_Unconditional : BfLocalVarAssignKind_None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
paramVar->mIsAssigned = true;
|
paramVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
if (methodDef->mMethodType != BfMethodType_Mixin)
|
if (methodDef->mMethodType != BfMethodType_Mixin)
|
||||||
paramVar->mIsReadOnly = true;
|
paramVar->mIsReadOnly = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,6 +119,13 @@ enum BfEmbeddedStatementFlags
|
||||||
BfEmbeddedStatementFlags_IsDeferredBlock = 2
|
BfEmbeddedStatementFlags_IsDeferredBlock = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum BfLocalVarAssignKind
|
||||||
|
{
|
||||||
|
BfLocalVarAssignKind_None = 0,
|
||||||
|
BfLocalVarAssignKind_Conditional = 1,
|
||||||
|
BfLocalVarAssignKind_Unconditional = 2
|
||||||
|
};
|
||||||
|
|
||||||
class BfLocalVariable
|
class BfLocalVariable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -143,7 +150,8 @@ public:
|
||||||
bool mIsStruct;
|
bool mIsStruct;
|
||||||
bool mIsImplicitParam;
|
bool mIsImplicitParam;
|
||||||
bool mParamFailed;
|
bool mParamFailed;
|
||||||
bool mIsAssigned;
|
BfLocalVarAssignKind mAssignedKind;
|
||||||
|
bool mHadExitBeforeAssign;
|
||||||
bool mIsReadOnly;
|
bool mIsReadOnly;
|
||||||
bool mIsSplat;
|
bool mIsSplat;
|
||||||
bool mIsLowered;
|
bool mIsLowered;
|
||||||
|
@ -155,20 +163,21 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfLocalVariable()
|
BfLocalVariable()
|
||||||
{
|
{
|
||||||
mUnassignedFieldFlags = 0;
|
mUnassignedFieldFlags = 0;
|
||||||
mResolvedType = NULL;
|
mResolvedType = NULL;
|
||||||
mNameNode = NULL;
|
mNameNode = NULL;
|
||||||
mLocalVarIdx = -1;
|
mLocalVarIdx = -1;
|
||||||
mLocalVarId = -1;
|
mLocalVarId = -1;
|
||||||
mCompositeCount = -1;
|
mCompositeCount = -1;
|
||||||
mParamIdx = -2;
|
mParamIdx = -2;
|
||||||
mIsThis = false;
|
mIsThis = false;
|
||||||
mHasLocalStructBacking = false;
|
mHasLocalStructBacking = false;
|
||||||
mIsStruct = false;
|
mIsStruct = false;
|
||||||
mIsImplicitParam = false;
|
mIsImplicitParam = false;
|
||||||
mParamFailed = false;
|
mParamFailed = false;
|
||||||
mIsAssigned = false;
|
mAssignedKind = BfLocalVarAssignKind_None;
|
||||||
|
mHadExitBeforeAssign = false;
|
||||||
mWrittenToId = -1;
|
mWrittenToId = -1;
|
||||||
mReadFromId = -1;
|
mReadFromId = -1;
|
||||||
mIsReadOnly = false;
|
mIsReadOnly = false;
|
||||||
|
@ -295,6 +304,59 @@ struct BfDeferredHandler
|
||||||
BfIRBlock mDoneBlock;
|
BfIRBlock mDoneBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BfScopeData;
|
||||||
|
|
||||||
|
struct BfAssignedLocal
|
||||||
|
{
|
||||||
|
BfLocalVariable* mLocalVar;
|
||||||
|
int mLocalVarField;
|
||||||
|
BfLocalVarAssignKind mAssignKind;
|
||||||
|
|
||||||
|
bool operator==(const BfAssignedLocal& second) const
|
||||||
|
{
|
||||||
|
return (mLocalVar == second.mLocalVar) && (mLocalVarField == second.mLocalVarField) && (mAssignKind == second.mAssignKind);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// We use this structure in the case where we have multiple execution paths, then we merge the assigned variables together
|
||||||
|
// So when we have "if (check) { a = 1; } else {a = 2; }" we can know that a IS definitely assigned afterwards
|
||||||
|
class BfDeferredLocalAssignData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BfScopeData* mScopeData;
|
||||||
|
int mVarIdBarrier;
|
||||||
|
SizedArray<BfAssignedLocal, 4> mAssignedLocals;
|
||||||
|
bool mIsChained;
|
||||||
|
BfDeferredLocalAssignData* mChainedAssignData;
|
||||||
|
bool mHadFallthrough;
|
||||||
|
bool mHadReturn;
|
||||||
|
bool mIsUnconditional;
|
||||||
|
bool mIsIfCondition;
|
||||||
|
bool mIfMayBeSkipped;
|
||||||
|
bool mLeftBlock;
|
||||||
|
|
||||||
|
public:
|
||||||
|
BfDeferredLocalAssignData(BfScopeData* scopeData = NULL)
|
||||||
|
{
|
||||||
|
mScopeData = scopeData;
|
||||||
|
mVarIdBarrier = -1;
|
||||||
|
mHadFallthrough = false;
|
||||||
|
mHadReturn = false;
|
||||||
|
mChainedAssignData = NULL;
|
||||||
|
mIsChained = false;
|
||||||
|
mIsUnconditional = false;
|
||||||
|
mIsIfCondition = false;
|
||||||
|
mIfMayBeSkipped = false;
|
||||||
|
mLeftBlock = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExtendFrom(BfDeferredLocalAssignData* outerLocalAssignData, bool doChain = false);
|
||||||
|
void BreakExtendChain();
|
||||||
|
void SetIntersection(const BfDeferredLocalAssignData& otherLocalAssignData);
|
||||||
|
void Validate() const;
|
||||||
|
void SetUnion(const BfDeferredLocalAssignData& otherLocalAssignData);
|
||||||
|
};
|
||||||
|
|
||||||
// "Looped" means this scope will execute zero to many times, "Conditional" means zero or one.
|
// "Looped" means this scope will execute zero to many times, "Conditional" means zero or one.
|
||||||
// Looped and Conditional are mutually exclusive. "Dyn" means Looped OR Conditional.
|
// Looped and Conditional are mutually exclusive. "Dyn" means Looped OR Conditional.
|
||||||
class BfScopeData
|
class BfScopeData
|
||||||
|
@ -330,6 +392,7 @@ public:
|
||||||
Array<BfDeferredHandler> mDeferredHandlers; // These get cleared when us our a parent gets new entries added into mDeferredCallEntries
|
Array<BfDeferredHandler> mDeferredHandlers; // These get cleared when us our a parent gets new entries added into mDeferredCallEntries
|
||||||
Array<BfIRBlock> mAtEndBlocks; // Move these to the end after we close scope
|
Array<BfIRBlock> mAtEndBlocks; // Move these to the end after we close scope
|
||||||
Array<BfIRValue> mDeferredLifetimeEnds;
|
Array<BfIRValue> mDeferredLifetimeEnds;
|
||||||
|
BfDeferredLocalAssignData* mExitLocalAssignData;
|
||||||
BfIRMDNode mAltDIFile;
|
BfIRMDNode mAltDIFile;
|
||||||
BfIRMDNode mAltDIScope;
|
BfIRMDNode mAltDIScope;
|
||||||
|
|
||||||
|
@ -355,11 +418,13 @@ public:
|
||||||
mMixinDepth = 0;
|
mMixinDepth = 0;
|
||||||
mScopeDepth = 0;
|
mScopeDepth = 0;
|
||||||
mScopeLocalId = -1;
|
mScopeLocalId = -1;
|
||||||
|
mExitLocalAssignData = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
~BfScopeData()
|
~BfScopeData()
|
||||||
{
|
{
|
||||||
mDeferredCallEntries.DeleteAll();
|
mDeferredCallEntries.DeleteAll();
|
||||||
|
delete mExitLocalAssignData;
|
||||||
}
|
}
|
||||||
|
|
||||||
BfScopeData* GetHead()
|
BfScopeData* GetHead()
|
||||||
|
@ -535,54 +600,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BfAssignedLocal
|
|
||||||
{
|
|
||||||
BfLocalVariable* mLocalVar;
|
|
||||||
int mLocalVarField;
|
|
||||||
|
|
||||||
bool operator==(const BfAssignedLocal& second) const
|
|
||||||
{
|
|
||||||
return (mLocalVar == second.mLocalVar) && (mLocalVarField == second.mLocalVarField);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// We use this structure in the case where we have multiple execution paths, then we merge the assigned variables together
|
|
||||||
// So when we have "if (check) { a = 1; } else {a = 2; }" we can know that a IS definitely assigned afterwards
|
|
||||||
class BfDeferredLocalAssignData
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
BfScopeData* mScopeData;
|
|
||||||
int mVarIdBarrier;
|
|
||||||
SizedArray<BfAssignedLocal, 4> mAssignedLocals;
|
|
||||||
bool mIsChained;
|
|
||||||
BfDeferredLocalAssignData* mChainedAssignData;
|
|
||||||
bool mHadFallthrough;
|
|
||||||
bool mHadReturn;
|
|
||||||
bool mIsUnconditional;
|
|
||||||
bool mIsIfCondition;
|
|
||||||
bool mIfMayBeSkipped;
|
|
||||||
|
|
||||||
public:
|
|
||||||
BfDeferredLocalAssignData(BfScopeData* scopeData = NULL)
|
|
||||||
{
|
|
||||||
mScopeData = scopeData;
|
|
||||||
mVarIdBarrier = -1;
|
|
||||||
mHadFallthrough = false;
|
|
||||||
mHadReturn = false;
|
|
||||||
mChainedAssignData = NULL;
|
|
||||||
mIsChained = false;
|
|
||||||
mIsUnconditional = false;
|
|
||||||
mIsIfCondition = false;
|
|
||||||
mIfMayBeSkipped = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ExtendFrom(BfDeferredLocalAssignData* outerLocalAssignData, bool doChain = false);
|
|
||||||
void BreakExtendChain();
|
|
||||||
void SetIntersection(const BfDeferredLocalAssignData& otherLocalAssignData);
|
|
||||||
void Validate() const;
|
|
||||||
void SetUnion(const BfDeferredLocalAssignData& otherLocalAssignData);
|
|
||||||
};
|
|
||||||
|
|
||||||
class BfMixinRecord
|
class BfMixinRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -910,7 +927,7 @@ public:
|
||||||
BfDeferredLocalAssignData* mDeferredLocalAssignData;
|
BfDeferredLocalAssignData* mDeferredLocalAssignData;
|
||||||
BfProjectSet mVisibleProjectSet;
|
BfProjectSet mVisibleProjectSet;
|
||||||
int mDeferredLoopListCount;
|
int mDeferredLoopListCount;
|
||||||
int mDeferredLoopListEntryCount;
|
int mDeferredLoopListEntryCount;
|
||||||
HashSet<int> mSkipObjectAccessChecks; // Indexed by BfIRValue value id
|
HashSet<int> mSkipObjectAccessChecks; // Indexed by BfIRValue value id
|
||||||
|
|
||||||
Dictionary<int64, BfType*>* mGenericTypeBindings;
|
Dictionary<int64, BfType*>* mGenericTypeBindings;
|
||||||
|
@ -995,7 +1012,7 @@ public:
|
||||||
mCurAccessId = 1;
|
mCurAccessId = 1;
|
||||||
mCurAppendAlign = 0;
|
mCurAppendAlign = 0;
|
||||||
mDeferredLoopListCount = 0;
|
mDeferredLoopListCount = 0;
|
||||||
mDeferredLoopListEntryCount = 0;
|
mDeferredLoopListEntryCount = 0;
|
||||||
mClosureState = NULL;
|
mClosureState = NULL;
|
||||||
mDeferredCallEmitState = NULL;
|
mDeferredCallEmitState = NULL;
|
||||||
mIteratorClassState = NULL;
|
mIteratorClassState = NULL;
|
||||||
|
@ -1120,7 +1137,7 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalDefined(BfLocalVariable* localVar, int fieldIdx = -1);
|
void LocalDefined(BfLocalVariable* localVar, int fieldIdx = -1, BfLocalVarAssignKind assignKind = BfLocalVarAssignKind_None, bool isFromDeferredAssignData = false);
|
||||||
void ApplyDeferredLocalAssignData(const BfDeferredLocalAssignData& deferredLocalAssignData);
|
void ApplyDeferredLocalAssignData(const BfDeferredLocalAssignData& deferredLocalAssignData);
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
|
|
|
@ -811,7 +811,7 @@ void BfModule::EmitDeferredCall(BfDeferredCallEntry& deferredCallEntry, bool mov
|
||||||
{
|
{
|
||||||
BfLocalVariable* localVar = new BfLocalVariable();
|
BfLocalVariable* localVar = new BfLocalVariable();
|
||||||
localVar->mIsReadOnly = true;
|
localVar->mIsReadOnly = true;
|
||||||
localVar->mIsAssigned = true;
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localVar->mReadFromId = 0;
|
localVar->mReadFromId = 0;
|
||||||
localVar->mName = capture.mName;
|
localVar->mName = capture.mName;
|
||||||
localVar->mValue = capture.mValue.mValue;
|
localVar->mValue = capture.mValue.mValue;
|
||||||
|
@ -1470,7 +1470,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
||||||
resolvedType = initValue.mType;
|
resolvedType = initValue.mType;
|
||||||
unresolvedType = resolvedType;
|
unresolvedType = resolvedType;
|
||||||
localDef->mLocalVarId = prevLocal->mLocalVarId;
|
localDef->mLocalVarId = prevLocal->mLocalVarId;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mIsShadow = true;
|
localDef->mIsShadow = true;
|
||||||
|
|
||||||
exprEvaluator.mResultLocalVarRefNode = varDecl->mNameNode;
|
exprEvaluator.mResultLocalVarRefNode = varDecl->mNameNode;
|
||||||
|
@ -1707,7 +1707,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1927,7 +1927,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD
|
||||||
varDecl->mNameNode->ToString(localDef->mName);
|
varDecl->mNameNode->ToString(localDef->mName);
|
||||||
localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
|
localDef->mNameNode = BfNodeDynCast<BfIdentifierNode>(varDecl->mNameNode);
|
||||||
localDef->mResolvedType = type;
|
localDef->mResolvedType = type;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mValue = val.mValue;
|
localDef->mValue = val.mValue;
|
||||||
if (isLet)
|
if (isLet)
|
||||||
{
|
{
|
||||||
|
@ -2104,7 +2104,7 @@ void BfModule::HandleTupleVariableDeclaration(BfVariableDeclaration* varDecl, Bf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
}
|
}
|
||||||
else if ((varDecl != NULL) && (varDecl->mInitializer == NULL))
|
else if ((varDecl != NULL) && (varDecl->mInitializer == NULL))
|
||||||
{
|
{
|
||||||
|
@ -3624,7 +3624,8 @@ void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool i
|
||||||
bool falseHadReturn = false;
|
bool falseHadReturn = false;
|
||||||
if (ifStmt->mFalseStatement != NULL)
|
if (ifStmt->mFalseStatement != NULL)
|
||||||
{
|
{
|
||||||
BfDeferredLocalAssignData falseDeferredLocalAssignData(mCurMethodState->mCurScope);
|
BfDeferredLocalAssignData falseDeferredLocalAssignData(&newScope);
|
||||||
|
falseDeferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
|
||||||
if (falseBB)
|
if (falseBB)
|
||||||
{
|
{
|
||||||
mBfIRBuilder->AddBlock(falseBB);
|
mBfIRBuilder->AddBlock(falseBB);
|
||||||
|
@ -4104,7 +4105,7 @@ void BfModule::Visit(BfSwitchStatement* switchStmt)
|
||||||
localDef->mName = "_";
|
localDef->mName = "_";
|
||||||
localDef->mResolvedType = switchValueAddr.mType;
|
localDef->mResolvedType = switchValueAddr.mType;
|
||||||
localDef->mIsReadOnly = true;
|
localDef->mIsReadOnly = true;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
if (switchValue.IsAddr())
|
if (switchValue.IsAddr())
|
||||||
{
|
{
|
||||||
localDef->mAddr = switchValue.mValue;
|
localDef->mAddr = switchValue.mValue;
|
||||||
|
@ -4884,7 +4885,15 @@ void BfModule::Visit(BfReturnStatement* returnStmt)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkScope = checkScope->mPrevScope;
|
checkScope = checkScope->mPrevScope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto checkLocalAssignData = mCurMethodState->mDeferredLocalAssignData;
|
||||||
|
while (checkLocalAssignData != NULL)
|
||||||
|
{
|
||||||
|
if (checkLocalAssignData->mScopeData != NULL)
|
||||||
|
checkLocalAssignData->mLeftBlock = true;
|
||||||
|
checkLocalAssignData = checkLocalAssignData->mChainedAssignData;
|
||||||
|
}
|
||||||
|
|
||||||
if (retType == NULL)
|
if (retType == NULL)
|
||||||
{
|
{
|
||||||
|
@ -5041,6 +5050,14 @@ void BfModule::Visit(BfBreakStatement* breakStmt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto checkLocalAssignData = mCurMethodState->mDeferredLocalAssignData;
|
||||||
|
while (checkLocalAssignData != NULL)
|
||||||
|
{
|
||||||
|
if ((checkLocalAssignData->mScopeData != NULL) && (checkLocalAssignData->mScopeData->mScopeDepth >= breakData->mScope->mScopeDepth))
|
||||||
|
checkLocalAssignData->mLeftBlock = true;
|
||||||
|
checkLocalAssignData = checkLocalAssignData->mChainedAssignData;
|
||||||
|
}
|
||||||
|
|
||||||
if (HasDeferredScopeCalls(breakData->mScope))
|
if (HasDeferredScopeCalls(breakData->mScope))
|
||||||
{
|
{
|
||||||
EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRBreakBlock);
|
EmitDeferredScopeCalls(true, breakData->mScope, breakData->mIRBreakBlock);
|
||||||
|
@ -5297,14 +5314,22 @@ void BfModule::Visit(BfDoStatement* doStmt)
|
||||||
breakData.mPrevBreakData = mCurMethodState->mBreakData;
|
breakData.mPrevBreakData = mCurMethodState->mBreakData;
|
||||||
SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
|
SetAndRestoreValue<BfBreakData*> prevBreakData(mCurMethodState->mBreakData, &breakData);
|
||||||
|
|
||||||
|
BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
|
||||||
|
deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, false);
|
||||||
|
deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
|
||||||
|
SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
|
||||||
|
|
||||||
// We may have a call in the loop body
|
// We may have a call in the loop body
|
||||||
mCurMethodState->mMayNeedThisAccessCheck = true;
|
mCurMethodState->mMayNeedThisAccessCheck = true;
|
||||||
|
|
||||||
mBfIRBuilder->CreateBr(bodyBB);
|
mBfIRBuilder->CreateBr(bodyBB);
|
||||||
mBfIRBuilder->SetInsertPoint(bodyBB);
|
mBfIRBuilder->SetInsertPoint(bodyBB);
|
||||||
VisitEmbeddedStatement(doStmt->mEmbeddedStatement);
|
VisitEmbeddedStatement(doStmt->mEmbeddedStatement);
|
||||||
|
|
||||||
|
prevDLA.Restore();
|
||||||
|
mCurMethodState->ApplyDeferredLocalAssignData(deferredLocalAssignData);
|
||||||
|
|
||||||
RestoreScopeState();
|
RestoreScopeState();
|
||||||
|
|
||||||
if (!mCurMethodState->mLeftBlockUncond)
|
if (!mCurMethodState->mLeftBlockUncond)
|
||||||
mBfIRBuilder->CreateBr(endBB);
|
mBfIRBuilder->CreateBr(endBB);
|
||||||
|
@ -5635,6 +5660,12 @@ void BfModule::DoForLess(BfForEachStatement* forEachStmt)
|
||||||
auto isLet = BfNodeDynCast<BfLetTypeReference>(forEachStmt->mVariableTypeRef) != 0;
|
auto isLet = BfNodeDynCast<BfLetTypeReference>(forEachStmt->mVariableTypeRef) != 0;
|
||||||
auto isVar = BfNodeDynCast<BfVarTypeReference>(forEachStmt->mVariableTypeRef) != 0;
|
auto isVar = BfNodeDynCast<BfVarTypeReference>(forEachStmt->mVariableTypeRef) != 0;
|
||||||
|
|
||||||
|
BfDeferredLocalAssignData deferredLocalAssignData(mCurMethodState->mCurScope);
|
||||||
|
deferredLocalAssignData.mIsIfCondition = true;
|
||||||
|
deferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData, true);
|
||||||
|
deferredLocalAssignData.mVarIdBarrier = mCurMethodState->GetRootMethodState()->mCurLocalVarId;
|
||||||
|
SetAndRestoreValue<BfDeferredLocalAssignData*> prevDLA(mCurMethodState->mDeferredLocalAssignData, &deferredLocalAssignData);
|
||||||
|
|
||||||
BfTypedValue target;
|
BfTypedValue target;
|
||||||
BfType* varType = NULL;
|
BfType* varType = NULL;
|
||||||
bool didInference = false;
|
bool didInference = false;
|
||||||
|
@ -5661,6 +5692,12 @@ void BfModule::DoForLess(BfForEachStatement* forEachStmt)
|
||||||
if (varType == NULL)
|
if (varType == NULL)
|
||||||
varType = GetPrimitiveType(BfTypeCode_IntPtr);
|
varType = GetPrimitiveType(BfTypeCode_IntPtr);
|
||||||
|
|
||||||
|
deferredLocalAssignData.mIsIfCondition = false;
|
||||||
|
|
||||||
|
// The "extend chain" is only valid for the conditional -- since that expression may contain unconditionally executed and
|
||||||
|
// conditionally executed code (in the case of "(GetVal(out a) && GetVal(out b))" for example
|
||||||
|
mCurMethodState->mDeferredLocalAssignData->BreakExtendChain();
|
||||||
|
|
||||||
BfType* checkType = varType;
|
BfType* checkType = varType;
|
||||||
if (checkType->IsTypedPrimitive())
|
if (checkType->IsTypedPrimitive())
|
||||||
checkType = checkType->GetUnderlyingType();
|
checkType = checkType->GetUnderlyingType();
|
||||||
|
@ -5683,7 +5720,7 @@ void BfModule::DoForLess(BfForEachStatement* forEachStmt)
|
||||||
varInst = CreateAlloca(varType);
|
varInst = CreateAlloca(varType);
|
||||||
}
|
}
|
||||||
localDef->mAddr = varInst;
|
localDef->mAddr = varInst;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mReadFromId = 0;
|
localDef->mReadFromId = 0;
|
||||||
localDef->mIsReadOnly = isLet || (forEachStmt->mReadOnlyToken != NULL);
|
localDef->mIsReadOnly = isLet || (forEachStmt->mReadOnlyToken != NULL);
|
||||||
|
|
||||||
|
@ -6146,7 +6183,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||||
localDef->mName = variableName;
|
localDef->mName = variableName;
|
||||||
localDef->mResolvedType = itr.mType;
|
localDef->mResolvedType = itr.mType;
|
||||||
localDef->mAddr = itr.mValue;
|
localDef->mAddr = itr.mValue;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mReadFromId = 0;
|
localDef->mReadFromId = 0;
|
||||||
localDef->Init();
|
localDef->Init();
|
||||||
UpdateSrcPos(forEachStmt);
|
UpdateSrcPos(forEachStmt);
|
||||||
|
@ -6184,7 +6221,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||||
if (!needsValCopy)
|
if (!needsValCopy)
|
||||||
localDef->mResolvedType = CreateRefType(localDef->mResolvedType);
|
localDef->mResolvedType = CreateRefType(localDef->mResolvedType);
|
||||||
localDef->mAddr = CreateAlloca(localDef->mResolvedType);
|
localDef->mAddr = CreateAlloca(localDef->mResolvedType);
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mReadFromId = 0;
|
localDef->mReadFromId = 0;
|
||||||
if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
|
if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
|
||||||
localDef->mIsReadOnly = true;
|
localDef->mIsReadOnly = true;
|
||||||
|
@ -6233,7 +6270,7 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||||
localDef->mResolvedType = varType;
|
localDef->mResolvedType = varType;
|
||||||
varInst = CreateAlloca(varType);
|
varInst = CreateAlloca(varType);
|
||||||
localDef->mAddr = varInst;
|
localDef->mAddr = varInst;
|
||||||
localDef->mIsAssigned = true;
|
localDef->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
localDef->mReadFromId = 0;
|
localDef->mReadFromId = 0;
|
||||||
if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
|
if ((isLet) || (forEachStmt->mReadOnlyToken != NULL))
|
||||||
localDef->mIsReadOnly = true;
|
localDef->mIsReadOnly = true;
|
||||||
|
@ -6935,7 +6972,7 @@ void BfModule::Visit(BfInlineAsmStatement* asmStmt)
|
||||||
{
|
{
|
||||||
// if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
|
// if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
|
||||||
checkLocal.mIsReadFrom = true;
|
checkLocal.mIsReadFrom = true;
|
||||||
checkLocal.mIsAssigned = true;
|
checkLocal.mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -7122,7 +7159,7 @@ void BfModule::Visit(BfInlineAsmStatement* asmStmt)
|
||||||
|
|
||||||
// if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
|
// if you access a variable in asm, we suppress any warnings related to used or assigned, regardless of usage
|
||||||
checkLocal.mIsReadFrom = true;
|
checkLocal.mIsReadFrom = true;
|
||||||
checkLocal.mIsAssigned = true;
|
checkLocal.mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
|
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue