mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Improved circular mixin check, isconst(expr), [ConstSkip]
This commit is contained in:
parent
cab9b3d9c7
commit
75333a0928
19 changed files with 241 additions and 60 deletions
|
@ -172,6 +172,12 @@ namespace System
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
[AttributeUsage(.Block)]
|
||||||
|
public struct ConstSkipAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[AttributeUsage(.Block)]
|
[AttributeUsage(.Block)]
|
||||||
public struct IgnoreErrorsAttribute : Attribute
|
public struct IgnoreErrorsAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
|
@ -1042,7 +1042,7 @@ namespace System
|
||||||
{
|
{
|
||||||
if (object == null)
|
if (object == null)
|
||||||
return;
|
return;
|
||||||
Append(object.ToString(.. scope .()));
|
Append(object.ToString(.. scope .(128)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void operator+=(String str)
|
public void operator+=(String str)
|
||||||
|
|
|
@ -145,6 +145,11 @@ namespace System
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(.Block)]
|
||||||
|
public struct ConstSkipAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
[AttributeUsage(.Block)]
|
[AttributeUsage(.Block)]
|
||||||
public struct IgnoreErrorsAttribute : Attribute
|
public struct IgnoreErrorsAttribute : Attribute
|
||||||
{
|
{
|
||||||
|
|
|
@ -356,6 +356,11 @@ void BfStructuralVisitor::Visit(BfOffsetOfExpression* offsetOfExpr)
|
||||||
Visit(offsetOfExpr->ToBase());
|
Visit(offsetOfExpr->ToBase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfStructuralVisitor::Visit(BfIsConstExpression* isConstExpr)
|
||||||
|
{
|
||||||
|
Visit(isConstExpr->ToBase());
|
||||||
|
}
|
||||||
|
|
||||||
void BfStructuralVisitor::Visit(BfDefaultExpression* defaultExpr)
|
void BfStructuralVisitor::Visit(BfDefaultExpression* defaultExpr)
|
||||||
{
|
{
|
||||||
Visit(defaultExpr->ToBase());
|
Visit(defaultExpr->ToBase());
|
||||||
|
@ -1398,6 +1403,8 @@ const char* Beefy::BfTokenToString(BfToken token)
|
||||||
return "internal";
|
return "internal";
|
||||||
case BfToken_Is:
|
case BfToken_Is:
|
||||||
return "is";
|
return "is";
|
||||||
|
case BfToken_IsConst:
|
||||||
|
return "isconst";
|
||||||
case BfToken_Let:
|
case BfToken_Let:
|
||||||
return "let";
|
return "let";
|
||||||
case BfToken_Mixin:
|
case BfToken_Mixin:
|
||||||
|
|
|
@ -158,6 +158,7 @@ enum BfToken : uint8
|
||||||
BfToken_Interface,
|
BfToken_Interface,
|
||||||
BfToken_Internal,
|
BfToken_Internal,
|
||||||
BfToken_Is,
|
BfToken_Is,
|
||||||
|
BfToken_IsConst,
|
||||||
BfToken_Let,
|
BfToken_Let,
|
||||||
BfToken_Mixin,
|
BfToken_Mixin,
|
||||||
BfToken_Mut,
|
BfToken_Mut,
|
||||||
|
@ -380,6 +381,7 @@ class BfSizeOfExpression;
|
||||||
class BfAlignOfExpression;
|
class BfAlignOfExpression;
|
||||||
class BfOffsetOfExpression;
|
class BfOffsetOfExpression;
|
||||||
class BfStrideOfExpression;
|
class BfStrideOfExpression;
|
||||||
|
class BfIsConstExpression;
|
||||||
class BfDefaultExpression;
|
class BfDefaultExpression;
|
||||||
class BfUninitializedExpression;
|
class BfUninitializedExpression;
|
||||||
class BfConditionalExpression;
|
class BfConditionalExpression;
|
||||||
|
@ -504,6 +506,7 @@ public:
|
||||||
virtual void Visit(BfAlignOfExpression* alignOfExpr);
|
virtual void Visit(BfAlignOfExpression* alignOfExpr);
|
||||||
virtual void Visit(BfStrideOfExpression* strideOfExpr);
|
virtual void Visit(BfStrideOfExpression* strideOfExpr);
|
||||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
||||||
|
virtual void Visit(BfIsConstExpression* isConstExpr);
|
||||||
virtual void Visit(BfDefaultExpression* defaultExpr);
|
virtual void Visit(BfDefaultExpression* defaultExpr);
|
||||||
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
||||||
virtual void Visit(BfCheckTypeExpression* checkTypeExpr);
|
virtual void Visit(BfCheckTypeExpression* checkTypeExpr);
|
||||||
|
@ -2691,6 +2694,7 @@ public:
|
||||||
BF_AST_TYPE(BfStrideOfExpression, BfTypeAttrExpression);
|
BF_AST_TYPE(BfStrideOfExpression, BfTypeAttrExpression);
|
||||||
}; BF_AST_DECL(BfStrideOfExpression, BfTypeAttrExpression);
|
}; BF_AST_DECL(BfStrideOfExpression, BfTypeAttrExpression);
|
||||||
|
|
||||||
|
|
||||||
class BfOffsetOfExpression : public BfTypeAttrExpression
|
class BfOffsetOfExpression : public BfTypeAttrExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -2700,6 +2704,17 @@ public:
|
||||||
BfIdentifierNode* mMemberName;
|
BfIdentifierNode* mMemberName;
|
||||||
}; BF_AST_DECL(BfOffsetOfExpression, BfTypeAttrExpression);
|
}; BF_AST_DECL(BfOffsetOfExpression, BfTypeAttrExpression);
|
||||||
|
|
||||||
|
class BfIsConstExpression : public BfExpression
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
BF_AST_TYPE(BfIsConstExpression, BfTypeAttrExpression);
|
||||||
|
|
||||||
|
BfTokenNode* mIsConstToken;
|
||||||
|
BfTokenNode* mOpenParen;
|
||||||
|
BfExpression* mExpression;
|
||||||
|
BfTokenNode* mCloseParen;
|
||||||
|
}; BF_AST_DECL(BfIsConstExpression, BfTypeAttrExpression);
|
||||||
|
|
||||||
class BfDefaultExpression : public BfExpression
|
class BfDefaultExpression : public BfExpression
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1718,7 +1718,7 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
|
||||||
{
|
{
|
||||||
"alignof", "as", "asm", "base", "break", "case", "catch", "checked", "continue", "default", "defer",
|
"alignof", "as", "asm", "base", "break", "case", "catch", "checked", "continue", "default", "defer",
|
||||||
"delegate", "delete", "do", "else", "false", "finally",
|
"delegate", "delete", "do", "else", "false", "finally",
|
||||||
"fixed", "for", "function", "if", "implicit", "in", "internal", "is", "new", "mixin", "null",
|
"fixed", "for", "function", "if", "implicit", "in", "internal", "is", "isconst", "new", "mixin", "null",
|
||||||
"offsetof", "out", "params", "ref", "rettype", "return",
|
"offsetof", "out", "params", "ref", "rettype", "return",
|
||||||
"sealed", "sizeof", "scope", "static", "strideof", "struct", "switch", /*"this",*/ "try", "true", "typeof", "unchecked",
|
"sealed", "sizeof", "scope", "static", "strideof", "struct", "switch", /*"this",*/ "try", "true", "typeof", "unchecked",
|
||||||
"using", "var", "virtual", "volatile", "where", "while",
|
"using", "var", "virtual", "volatile", "where", "while",
|
||||||
|
@ -3570,6 +3570,8 @@ String BfAutoComplete::ConstantToString(BfIRConstHolder* constHolder, BfIRValue
|
||||||
auto constant = constHolder->GetConstant(id);
|
auto constant = constHolder->GetConstant(id);
|
||||||
switch (constant->mTypeCode)
|
switch (constant->mTypeCode)
|
||||||
{
|
{
|
||||||
|
case BfTypeCode_Boolean:
|
||||||
|
return StrFormat(":(bool) %s", constant->mBool ? "true" : "false");
|
||||||
case BfTypeCode_UInt8:
|
case BfTypeCode_UInt8:
|
||||||
return StrFormat(":(uint8) %llu", constant->mUInt64);
|
return StrFormat(":(uint8) %llu", constant->mUInt64);
|
||||||
case BfTypeCode_UInt16:
|
case BfTypeCode_UInt16:
|
||||||
|
|
|
@ -474,6 +474,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
||||||
mObsoleteAttributeTypeDef = NULL;
|
mObsoleteAttributeTypeDef = NULL;
|
||||||
mErrorAttributeTypeDef = NULL;
|
mErrorAttributeTypeDef = NULL;
|
||||||
mWarnAttributeTypeDef = NULL;
|
mWarnAttributeTypeDef = NULL;
|
||||||
|
mConstSkipAttributeTypeDef = NULL;
|
||||||
mIgnoreErrorsAttributeTypeDef = NULL;
|
mIgnoreErrorsAttributeTypeDef = NULL;
|
||||||
mReflectAttributeTypeDef = NULL;
|
mReflectAttributeTypeDef = NULL;
|
||||||
mOnCompileAttributeTypeDef = NULL;
|
mOnCompileAttributeTypeDef = NULL;
|
||||||
|
@ -7104,6 +7105,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
||||||
mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
|
mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
|
||||||
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
|
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
|
||||||
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
|
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
|
||||||
|
mConstSkipAttributeTypeDef = _GetRequiredType("System.ConstSkipAttribute");
|
||||||
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
|
mIgnoreErrorsAttributeTypeDef = _GetRequiredType("System.IgnoreErrorsAttribute");
|
||||||
mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute");
|
mReflectAttributeTypeDef = _GetRequiredType("System.ReflectAttribute");
|
||||||
mOnCompileAttributeTypeDef = _GetRequiredType("System.OnCompileAttribute");
|
mOnCompileAttributeTypeDef = _GetRequiredType("System.OnCompileAttribute");
|
||||||
|
|
|
@ -454,6 +454,7 @@ public:
|
||||||
BfTypeDef* mObsoleteAttributeTypeDef;
|
BfTypeDef* mObsoleteAttributeTypeDef;
|
||||||
BfTypeDef* mErrorAttributeTypeDef;
|
BfTypeDef* mErrorAttributeTypeDef;
|
||||||
BfTypeDef* mWarnAttributeTypeDef;
|
BfTypeDef* mWarnAttributeTypeDef;
|
||||||
|
BfTypeDef* mConstSkipAttributeTypeDef;
|
||||||
BfTypeDef* mIgnoreErrorsAttributeTypeDef;
|
BfTypeDef* mIgnoreErrorsAttributeTypeDef;
|
||||||
BfTypeDef* mReflectAttributeTypeDef;
|
BfTypeDef* mReflectAttributeTypeDef;
|
||||||
BfTypeDef* mOnCompileAttributeTypeDef;
|
BfTypeDef* mOnCompileAttributeTypeDef;
|
||||||
|
|
|
@ -528,6 +528,16 @@ void BfElementVisitor::Visit(BfDefaultExpression* defaultExpr)
|
||||||
VisitChild(defaultExpr->mCloseParen);
|
VisitChild(defaultExpr->mCloseParen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfElementVisitor::Visit(BfIsConstExpression* isConstExpr)
|
||||||
|
{
|
||||||
|
Visit(isConstExpr->ToBase());
|
||||||
|
|
||||||
|
VisitChild(isConstExpr->mIsConstToken);
|
||||||
|
VisitChild(isConstExpr->mOpenParen);
|
||||||
|
VisitChild(isConstExpr->mExpression);
|
||||||
|
VisitChild(isConstExpr->mCloseParen);
|
||||||
|
}
|
||||||
|
|
||||||
void BfElementVisitor::Visit(BfUninitializedExpression* uninitializedExpr)
|
void BfElementVisitor::Visit(BfUninitializedExpression* uninitializedExpr)
|
||||||
{
|
{
|
||||||
Visit(uninitializedExpr->ToBase());
|
Visit(uninitializedExpr->ToBase());
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
virtual void Visit(BfTypeAttrExpression* typeAttrExpr);
|
virtual void Visit(BfTypeAttrExpression* typeAttrExpr);
|
||||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
virtual void Visit(BfOffsetOfExpression* offsetOfExpr);
|
||||||
virtual void Visit(BfDefaultExpression* defaultExpr);
|
virtual void Visit(BfDefaultExpression* defaultExpr);
|
||||||
|
virtual void Visit(BfIsConstExpression* isConstExpr);
|
||||||
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
virtual void Visit(BfUninitializedExpression* uninitializedExpr);
|
||||||
virtual void Visit(BfCheckTypeExpression* checkTypeExpr);
|
virtual void Visit(BfCheckTypeExpression* checkTypeExpr);
|
||||||
virtual void Visit(BfDynamicCastExpression* dynCastExpr);
|
virtual void Visit(BfDynamicCastExpression* dynCastExpr);
|
||||||
|
|
|
@ -3344,6 +3344,19 @@ void BfExprEvaluator::Visit(BfAttributedExpression* attribExpr)
|
||||||
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (attributeState.mCustomAttributes->Contains(mModule->mCompiler->mConstSkipAttributeTypeDef))
|
||||||
|
{
|
||||||
|
if ((mModule->mCurMethodState == NULL) || (mModule->mCurMethodState->mCurScope == NULL) || (!mModule->mCurMethodState->mCurScope->mInConstIgnore))
|
||||||
|
{
|
||||||
|
VisitChild(attribExpr->mExpression);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BF_ASSERT(mModule->mBfIRBuilder->mIgnoreWrites);
|
||||||
|
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
|
||||||
|
}
|
||||||
|
attributeState.mUsed = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VisitChild(attribExpr->mExpression);
|
VisitChild(attribExpr->mExpression);
|
||||||
|
@ -11480,7 +11493,6 @@ void BfExprEvaluator::DoTypeIntAttr(BfTypeReference* typeRef, BfTokenNode* comma
|
||||||
{
|
{
|
||||||
auto autoComplete = GetAutoComplete();
|
auto autoComplete = GetAutoComplete();
|
||||||
|
|
||||||
|
|
||||||
auto type = mModule->ResolveTypeRef(typeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AutoComplete);
|
auto type = mModule->ResolveTypeRef(typeRef, BfPopulateType_Data, BfResolveTypeRefFlag_AutoComplete);
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -11612,6 +11624,30 @@ void BfExprEvaluator::Visit(BfOffsetOfExpression* offsetOfExpr)
|
||||||
DoTypeIntAttr(offsetOfExpr->mTypeRef, offsetOfExpr->mCommaToken, offsetOfExpr->mMemberName, BfToken_OffsetOf);
|
DoTypeIntAttr(offsetOfExpr->mTypeRef, offsetOfExpr->mCommaToken, offsetOfExpr->mMemberName, BfToken_OffsetOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfExprEvaluator::Visit(BfIsConstExpression* isConstExpr)
|
||||||
|
{
|
||||||
|
if (isConstExpr->mExpression == NULL)
|
||||||
|
{
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfMethodState methodState;
|
||||||
|
SetAndRestoreValue<BfMethodState*> prevMethodState(mModule->mCurMethodState, &methodState, false);
|
||||||
|
if (mModule->mCurMethodState == NULL)
|
||||||
|
prevMethodState.Set();
|
||||||
|
methodState.mTempKind = BfMethodState::TempKind_NonStatic;
|
||||||
|
|
||||||
|
SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> allowUninitReads(mModule->mCurMethodState->mAllowUinitReads, true);
|
||||||
|
|
||||||
|
BfEvalExprFlags exprFlags = BfEvalExprFlags_None;
|
||||||
|
|
||||||
|
auto result = mModule->CreateValueFromExpression(isConstExpr->mExpression, NULL, BfEvalExprFlags_DeclType);
|
||||||
|
bool isConst = mModule->mBfIRBuilder->IsConstValue(result.mValue);
|
||||||
|
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, isConst ? 1 : 0), mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||||
|
}
|
||||||
|
|
||||||
void BfExprEvaluator::Visit(BfDefaultExpression* defaultExpr)
|
void BfExprEvaluator::Visit(BfDefaultExpression* defaultExpr)
|
||||||
{
|
{
|
||||||
auto autoComplete = GetAutoComplete();
|
auto autoComplete = GetAutoComplete();
|
||||||
|
@ -11669,7 +11705,7 @@ void BfExprEvaluator::Visit(BfCheckTypeExpression* checkTypeExpr)
|
||||||
if (autoComplete != NULL)
|
if (autoComplete != NULL)
|
||||||
autoComplete->CheckTypeRef(checkTypeExpr->mTypeRef, false, true);
|
autoComplete->CheckTypeRef(checkTypeExpr->mTypeRef, false, true);
|
||||||
|
|
||||||
auto targetType = mModule->ResolveTypeRef(checkTypeExpr->mTypeRef);
|
auto targetType = mModule->ResolveTypeRef(checkTypeExpr->mTypeRef, BfPopulateType_Declaration);
|
||||||
if (!targetType)
|
if (!targetType)
|
||||||
{
|
{
|
||||||
mModule->AssertErrorState();
|
mModule->AssertErrorState();
|
||||||
|
@ -16442,41 +16478,6 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
auto curMethodState = mModule->mCurMethodState;
|
auto curMethodState = mModule->mCurMethodState;
|
||||||
//
|
|
||||||
|
|
||||||
// Why was this required? It doesn't check for matching generic args (we only want to throw an error if we call back into a mixin with the same generic args as before)
|
|
||||||
// {
|
|
||||||
// bool hasCircularRef = false;
|
|
||||||
//
|
|
||||||
// auto checkMethodState = curMethodState;
|
|
||||||
// while (checkMethodState != NULL)
|
|
||||||
// {
|
|
||||||
// auto curMixinState = checkMethodState->mMixinState;
|
|
||||||
// while (curMixinState != NULL)
|
|
||||||
// {
|
|
||||||
// if (curMixinState->mSource == targetSrc)
|
|
||||||
// hasCircularRef = true;
|
|
||||||
// curMixinState = curMixinState->mPrevMixinState;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if ((checkMethodState->mClosureState != NULL) && (checkMethodState->mClosureState->mActiveDeferredLocalMethod != NULL))
|
|
||||||
// {
|
|
||||||
// for (auto& mixinRecord : checkMethodState->mClosureState->mActiveDeferredLocalMethod->mMixinStateRecords)
|
|
||||||
// {
|
|
||||||
// if (mixinRecord.mSource == targetSrc)
|
|
||||||
// hasCircularRef = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// checkMethodState = checkMethodState->mPrevMethodState;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (hasCircularRef)
|
|
||||||
// {
|
|
||||||
// mModule->Fail("Circular reference detected between mixins", targetSrc);
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
auto moduleMethodInstance = GetSelectedMethod(targetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
|
auto moduleMethodInstance = GetSelectedMethod(targetSrc, methodMatcher.mBestMethodTypeInstance, methodMatcher.mBestMethodDef, methodMatcher);
|
||||||
if (!moduleMethodInstance)
|
if (!moduleMethodInstance)
|
||||||
|
@ -16522,30 +16523,78 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check circular ref based on methodInstance
|
if (curMethodState->mCurScope->mMixinDepth >= 128)
|
||||||
|
{
|
||||||
|
mModule->Fail("Maximum nested mixin depth exceeded", targetSrc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check circular ref based on methodInstance. We must check the arg types since we could be making progress in mixin evaluation
|
||||||
|
// based on method selection within the mixin dependent on args
|
||||||
{
|
{
|
||||||
bool hasCircularRef = false;
|
bool hasCircularRef = false;
|
||||||
|
|
||||||
|
BfMixinState* checkMixinState = NULL;
|
||||||
|
|
||||||
auto checkMethodState = curMethodState;
|
auto checkMethodState = curMethodState;
|
||||||
while (checkMethodState != NULL)
|
while (checkMethodState != NULL)
|
||||||
{
|
{
|
||||||
if (checkMethodState->mMethodInstance == methodInstance)
|
|
||||||
hasCircularRef = true;
|
|
||||||
|
|
||||||
auto curMixinState = checkMethodState->mMixinState;
|
auto curMixinState = checkMethodState->mMixinState;
|
||||||
while (curMixinState != NULL)
|
while (curMixinState != NULL)
|
||||||
{
|
{
|
||||||
if (curMixinState->mMixinMethodInstance == methodInstance)
|
if ((curMixinState->mDoCircularVarResult) && (curMixinState->mMixinMethodInstance == methodInstance))
|
||||||
hasCircularRef = true;
|
{
|
||||||
curMixinState = curMixinState->mPrevMixinState;
|
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!curMixinState->mCheckedCircularRef) && (curMixinState->mMixinMethodInstance == methodInstance))
|
||||||
|
{
|
||||||
|
checkMixinState = curMixinState;
|
||||||
|
checkMixinState->mCheckedCircularRef = true;
|
||||||
|
}
|
||||||
|
else if (checkMixinState != NULL)
|
||||||
|
{
|
||||||
|
if ((curMixinState->mMixinMethodInstance == checkMixinState->mMixinMethodInstance) &&
|
||||||
|
(curMixinState->mArgTypes == checkMixinState->mArgTypes) &&
|
||||||
|
(curMixinState->mArgConsts.mSize == checkMixinState->mArgConsts.mSize))
|
||||||
|
{
|
||||||
|
bool constsMatch = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < curMixinState->mArgConsts.mSize; i++)
|
||||||
|
{
|
||||||
|
if (!mModule->mBfIRBuilder->CheckConstEquality(curMixinState->mArgConsts[i], checkMixinState->mArgConsts[i]))
|
||||||
|
{
|
||||||
|
constsMatch = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (constsMatch)
|
||||||
|
hasCircularRef = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
curMixinState = curMixinState->mPrevMixinState;
|
||||||
|
}
|
||||||
|
|
||||||
checkMethodState = checkMethodState->mPrevMethodState;
|
checkMethodState = checkMethodState->mPrevMethodState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasCircularRef)
|
if (hasCircularRef)
|
||||||
{
|
{
|
||||||
|
for (auto argType : checkMixinState->mArgTypes)
|
||||||
|
{
|
||||||
|
if (argType->IsVar())
|
||||||
|
checkMixinState->mDoCircularVarResult = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkMixinState->mDoCircularVarResult)
|
||||||
|
{
|
||||||
|
mResult = mModule->GetDefaultTypedValue(mModule->GetPrimitiveType(BfTypeCode_Var));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mModule->Fail("Circular reference detected between mixins", targetSrc);
|
mModule->Fail("Circular reference detected between mixins", targetSrc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -16981,6 +17030,9 @@ void BfExprEvaluator::InjectMixin(BfAstNode* targetSrc, BfTypedValue target, boo
|
||||||
}
|
}
|
||||||
|
|
||||||
newLocalVar->mParamIdx = -3;
|
newLocalVar->mParamIdx = -3;
|
||||||
|
mixinState->mArgTypes.Add(newLocalVar->mResolvedType);
|
||||||
|
if (mModule->mBfIRBuilder->IsConstValue(newLocalVar->mConstValue))
|
||||||
|
mixinState->mArgConsts.Add(newLocalVar->mConstValue);
|
||||||
};
|
};
|
||||||
|
|
||||||
argExprEvaluatorItr = argExprEvaluators.begin();
|
argExprEvaluatorItr = argExprEvaluators.begin();
|
||||||
|
@ -18993,13 +19045,14 @@ void BfExprEvaluator::Visit(BfConditionalExpression* condExpr)
|
||||||
{
|
{
|
||||||
auto curBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
auto curBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
||||||
SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> ignoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mModule->mCurMethodState->mCurScope->mInConstIgnore, true);
|
||||||
ignoredValue = mModule->CreateValueFromExpression(ignoredExpr, mExpectingType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast));
|
ignoredValue = mModule->CreateValueFromExpression(ignoredExpr, mExpectingType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast));
|
||||||
mModule->mBfIRBuilder->SetInsertPoint(curBlock);
|
mModule->mBfIRBuilder->SetInsertPoint(curBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!actualValue)
|
if (!actualValue)
|
||||||
return;
|
return;
|
||||||
if ((ignoredValue) && (ignoredValue.mType != actualValue.mType))
|
if ((ignoredValue) && (ignoredValue.mType != actualValue.mType) && (!ignoredValue.mType->IsVar()))
|
||||||
{
|
{
|
||||||
// Cast to more specific 'ignored' type if applicable
|
// Cast to more specific 'ignored' type if applicable
|
||||||
if (mModule->CanCast(actualValue, ignoredValue.mType))
|
if (mModule->CanCast(actualValue, ignoredValue.mType))
|
||||||
|
@ -22079,6 +22132,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
|
||||||
{
|
{
|
||||||
// Always false
|
// Always false
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mModule->mCurMethodState->mCurScope->mInConstIgnore, true);
|
||||||
rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags));
|
rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags));
|
||||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), boolType);
|
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0), boolType);
|
||||||
}
|
}
|
||||||
|
@ -22131,6 +22185,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp
|
||||||
{
|
{
|
||||||
// Always true
|
// Always true
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mModule->mCurMethodState->mCurScope->mInConstIgnore, true);
|
||||||
rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags));
|
rightValue = mModule->CreateValueFromExpression(rightExpression, boolType, (BfEvalExprFlags)(mBfEvalExprFlags & BfEvalExprFlags_InheritFlags));
|
||||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), boolType);
|
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 1), boolType);
|
||||||
}
|
}
|
||||||
|
@ -22208,6 +22263,7 @@ bool BfExprEvaluator::PerformBinaryOperation_NullCoalesce(BfTokenNode* opToken,
|
||||||
|
|
||||||
// Already have a value, we don't need the right side
|
// Already have a value, we don't need the right side
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mModule->mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mModule->mCurMethodState->mCurScope->mInConstIgnore, true);
|
||||||
mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_CreateConditionalScope));
|
mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_CreateConditionalScope));
|
||||||
mResult = leftValue;
|
mResult = leftValue;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -549,6 +549,7 @@ public:
|
||||||
virtual void Visit(BfAlignOfExpression* alignOfExpr) override;
|
virtual void Visit(BfAlignOfExpression* alignOfExpr) override;
|
||||||
virtual void Visit(BfStrideOfExpression* strideOfExpr) override;
|
virtual void Visit(BfStrideOfExpression* strideOfExpr) override;
|
||||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr) override;
|
virtual void Visit(BfOffsetOfExpression* offsetOfExpr) override;
|
||||||
|
virtual void Visit(BfIsConstExpression* isConstExpr) override;
|
||||||
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
||||||
virtual void Visit(BfUninitializedExpression* uninitialziedExpr) override;
|
virtual void Visit(BfUninitializedExpression* uninitialziedExpr) override;
|
||||||
virtual void Visit(BfCheckTypeExpression* checkTypeExpr) override;
|
virtual void Visit(BfCheckTypeExpression* checkTypeExpr) override;
|
||||||
|
|
|
@ -445,6 +445,7 @@ public:
|
||||||
bool mAllowVariableDeclarations;
|
bool mAllowVariableDeclarations;
|
||||||
bool mInInitBlock;
|
bool mInInitBlock;
|
||||||
bool mSupressNextUnreachable;
|
bool mSupressNextUnreachable;
|
||||||
|
bool mInConstIgnore;
|
||||||
BfMixinState* mMixinState;
|
BfMixinState* mMixinState;
|
||||||
BfBlock* mAstBlock;
|
BfBlock* mAstBlock;
|
||||||
BfAstNode* mCloseNode;
|
BfAstNode* mCloseNode;
|
||||||
|
@ -484,6 +485,7 @@ public:
|
||||||
mAllowTargeting = true;
|
mAllowTargeting = true;
|
||||||
mAllowVariableDeclarations = true;
|
mAllowVariableDeclarations = true;
|
||||||
mInInitBlock = false;
|
mInInitBlock = false;
|
||||||
|
mInConstIgnore = false;
|
||||||
mMixinDepth = 0;
|
mMixinDepth = 0;
|
||||||
mScopeDepth = 0;
|
mScopeDepth = 0;
|
||||||
mScopeLocalId = -1;
|
mScopeLocalId = -1;
|
||||||
|
@ -802,15 +804,30 @@ public:
|
||||||
BfFilePosition mInjectFilePosition;
|
BfFilePosition mInjectFilePosition;
|
||||||
BfMethodInstance* mMixinMethodInstance;
|
BfMethodInstance* mMixinMethodInstance;
|
||||||
BfAstNode* mResultExpr;
|
BfAstNode* mResultExpr;
|
||||||
|
SizedArray<BfType*, 8> mArgTypes;
|
||||||
|
SizedArray<BfIRValue, 8> mArgConsts;
|
||||||
int mLocalsStartIdx;
|
int mLocalsStartIdx;
|
||||||
bool mUsedInvocationScope;
|
bool mUsedInvocationScope;
|
||||||
bool mHasDeferredUsage;
|
bool mHasDeferredUsage;
|
||||||
|
bool mCheckedCircularRef;
|
||||||
|
bool mDoCircularVarResult;
|
||||||
BfTypedValue mTarget;
|
BfTypedValue mTarget;
|
||||||
int mLastTargetAccessId;
|
int mLastTargetAccessId;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BfMixinState()
|
BfMixinState()
|
||||||
{
|
{
|
||||||
|
mPrevMixinState = NULL;
|
||||||
|
mSource = NULL;
|
||||||
|
mCallerScope = NULL;
|
||||||
|
mTarget = NULL;
|
||||||
|
mMixinMethodInstance = NULL;
|
||||||
|
mResultExpr = NULL;
|
||||||
|
mLocalsStartIdx = 0;
|
||||||
|
mUsedInvocationScope = false;
|
||||||
|
mHasDeferredUsage = false;
|
||||||
|
mCheckedCircularRef = false;
|
||||||
|
mDoCircularVarResult = false;
|
||||||
mLastTargetAccessId = -1;
|
mLastTargetAccessId = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,6 +1143,7 @@ public:
|
||||||
newScopeData->mPrevScope = mCurScope;
|
newScopeData->mPrevScope = mCurScope;
|
||||||
newScopeData->mMixinDepth = mCurScope->mMixinDepth;
|
newScopeData->mMixinDepth = mCurScope->mMixinDepth;
|
||||||
newScopeData->mScopeDepth = mCurScope->mScopeDepth + 1;
|
newScopeData->mScopeDepth = mCurScope->mScopeDepth + 1;
|
||||||
|
newScopeData->mInConstIgnore = mCurScope->mInConstIgnore;
|
||||||
mCurScope = newScopeData;
|
mCurScope = newScopeData;
|
||||||
mTailScope = mCurScope;
|
mTailScope = mCurScope;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3143,6 +3143,10 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate, bool disablePrepro
|
||||||
if ((!mCompatMode) && (SrcPtrHasToken("is")))
|
if ((!mCompatMode) && (SrcPtrHasToken("is")))
|
||||||
mToken = BfToken_Is;
|
mToken = BfToken_Is;
|
||||||
break;
|
break;
|
||||||
|
case TOKEN_HASH('i', 's', 'c', 'o'):
|
||||||
|
if ((!mCompatMode) && (SrcPtrHasToken("isconst")))
|
||||||
|
mToken = BfToken_IsConst;
|
||||||
|
break;
|
||||||
case TOKEN_HASH('l', 'e', 't', 0):
|
case TOKEN_HASH('l', 'e', 't', 0):
|
||||||
if ((!mCompatMode) && (SrcPtrHasToken("let")))
|
if ((!mCompatMode) && (SrcPtrHasToken("let")))
|
||||||
mToken = BfToken_Let;
|
mToken = BfToken_Let;
|
||||||
|
|
|
@ -1764,6 +1764,16 @@ void BfPrinter::Visit(BfDefaultExpression* defaultExpr)
|
||||||
VisitChild(defaultExpr->mCloseParen);
|
VisitChild(defaultExpr->mCloseParen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfPrinter::Visit(BfIsConstExpression* isConstExpr)
|
||||||
|
{
|
||||||
|
Visit(isConstExpr->ToBase());
|
||||||
|
|
||||||
|
VisitChild(isConstExpr->mIsConstToken);
|
||||||
|
VisitChild(isConstExpr->mOpenParen);
|
||||||
|
VisitChild(isConstExpr->mExpression);
|
||||||
|
VisitChild(isConstExpr->mCloseParen);
|
||||||
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfCheckTypeExpression* checkTypeExpr)
|
void BfPrinter::Visit(BfCheckTypeExpression* checkTypeExpr)
|
||||||
{
|
{
|
||||||
Visit(checkTypeExpr->ToBase());
|
Visit(checkTypeExpr->ToBase());
|
||||||
|
|
|
@ -175,6 +175,7 @@ public:
|
||||||
virtual void Visit(BfSizeOfExpression* sizeOfExpr) override;
|
virtual void Visit(BfSizeOfExpression* sizeOfExpr) override;
|
||||||
virtual void Visit(BfOffsetOfExpression* offsetOfExpr) override;
|
virtual void Visit(BfOffsetOfExpression* offsetOfExpr) override;
|
||||||
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
virtual void Visit(BfDefaultExpression* defaultExpr) override;
|
||||||
|
virtual void Visit(BfIsConstExpression* isConstExpr) override;
|
||||||
virtual void Visit(BfCheckTypeExpression* checkTypeExpr) override;
|
virtual void Visit(BfCheckTypeExpression* checkTypeExpr) override;
|
||||||
virtual void Visit(BfDynamicCastExpression* dynCastExpr) override;
|
virtual void Visit(BfDynamicCastExpression* dynCastExpr) override;
|
||||||
virtual void Visit(BfCastExpression* castExpr) override;
|
virtual void Visit(BfCastExpression* castExpr) override;
|
||||||
|
|
|
@ -1998,6 +1998,19 @@ BfExpression* BfReducer::CreateExpression(BfAstNode* node, CreateExprFlags creat
|
||||||
|
|
||||||
exprLeft = defaultExpr;
|
exprLeft = defaultExpr;
|
||||||
}
|
}
|
||||||
|
else if (token == BfToken_IsConst)
|
||||||
|
{
|
||||||
|
auto isConstExpr = mAlloc->Alloc<BfIsConstExpression>();
|
||||||
|
ReplaceNode(tokenNode, isConstExpr);
|
||||||
|
isConstExpr->mIsConstToken = tokenNode;
|
||||||
|
tokenNode = ExpectTokenAfter(isConstExpr, BfToken_LParen);
|
||||||
|
MEMBER_SET_CHECKED(isConstExpr, mOpenParen, tokenNode);
|
||||||
|
auto expr = CreateExpressionAfter(isConstExpr);
|
||||||
|
MEMBER_SET_CHECKED(isConstExpr, mExpression, expr);
|
||||||
|
tokenNode = ExpectTokenAfter(isConstExpr, BfToken_RParen);
|
||||||
|
MEMBER_SET_CHECKED(isConstExpr, mCloseParen, tokenNode);
|
||||||
|
exprLeft = isConstExpr;
|
||||||
|
}
|
||||||
else if (token == BfToken_Question)
|
else if (token == BfToken_Question)
|
||||||
{
|
{
|
||||||
auto uninitExpr = mAlloc->Alloc<BfUninitializedExpression>();
|
auto uninitExpr = mAlloc->Alloc<BfUninitializedExpression>();
|
||||||
|
|
|
@ -3221,6 +3221,7 @@ void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupCon
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
ctx->mModule->Fail("Generic argument expected", genericTypeRef->mOpenChevron);
|
||||||
ctx->mFailed = true;
|
ctx->mFailed = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3742,11 +3742,16 @@ void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool i
|
||||||
|
|
||||||
if (includeTrueStmt)
|
if (includeTrueStmt)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mCurMethodState->mCurScope->mInConstIgnore);
|
||||||
|
|
||||||
if (trueBB)
|
if (trueBB)
|
||||||
mBfIRBuilder->SetInsertPoint(trueBB);
|
mBfIRBuilder->SetInsertPoint(trueBB);
|
||||||
if ((isConstBranch) && (constResult != true))
|
if ((isConstBranch) && (constResult != true))
|
||||||
|
{
|
||||||
mBfIRBuilder->mIgnoreWrites = true;
|
mBfIRBuilder->mIgnoreWrites = true;
|
||||||
|
mCurMethodState->mCurScope->mInConstIgnore = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ignoredLastBlock = false;
|
ignoredLastBlock = false;
|
||||||
VisitEmbeddedStatement(ifStmt->mTrueStatement);
|
VisitEmbeddedStatement(ifStmt->mTrueStatement);
|
||||||
|
@ -3785,9 +3790,14 @@ void BfModule::DoIfStatement(BfIfStatement* ifStmt, bool includeTrueStmt, bool i
|
||||||
ignoredLastBlock = true;
|
ignoredLastBlock = true;
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mCurMethodState->mCurScope->mInConstIgnore);
|
||||||
|
|
||||||
if ((isConstBranch) && (constResult != false))
|
if ((isConstBranch) && (constResult != false))
|
||||||
|
{
|
||||||
mBfIRBuilder->mIgnoreWrites = true;
|
mBfIRBuilder->mIgnoreWrites = true;
|
||||||
|
mCurMethodState->mCurScope->mInConstIgnore = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ignoredLastBlock = false;
|
ignoredLastBlock = false;
|
||||||
falseDeferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
|
falseDeferredLocalAssignData.ExtendFrom(mCurMethodState->mDeferredLocalAssignData);
|
||||||
|
@ -3898,6 +3908,18 @@ void BfModule::Visit(BfAttributedStatement* attribStmt)
|
||||||
VisitChild(attribStmt->mStatement);
|
VisitChild(attribStmt->mStatement);
|
||||||
attributeState.mUsed = true;
|
attributeState.mUsed = true;
|
||||||
}
|
}
|
||||||
|
else if (attributeState.mCustomAttributes->Contains(mCompiler->mConstSkipAttributeTypeDef))
|
||||||
|
{
|
||||||
|
if ((mCurMethodState == NULL) || (mCurMethodState->mCurScope == NULL) || (!mCurMethodState->mCurScope->mInConstIgnore))
|
||||||
|
{
|
||||||
|
VisitChild(attribStmt->mStatement);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BF_ASSERT(mBfIRBuilder->mIgnoreWrites);
|
||||||
|
}
|
||||||
|
attributeState.mUsed = true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
VisitChild(attribStmt->mStatement);
|
VisitChild(attribStmt->mStatement);
|
||||||
|
@ -4755,7 +4777,9 @@ void BfModule::Visit(BfSwitchStatement* switchStmt)
|
||||||
|
|
||||||
auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
|
auto prevInsertBlock = mBfIRBuilder->GetInsertBlock();
|
||||||
|
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, !mayHaveMatch && !prevHadFallthrough);
|
bool isConstIgnore = !mayHaveMatch && !prevHadFallthrough;
|
||||||
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, isConstIgnore);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mCurMethodState->mCurScope->mInConstIgnore, true, isConstIgnore);
|
||||||
|
|
||||||
mBfIRBuilder->AddBlock(caseBlock);
|
mBfIRBuilder->AddBlock(caseBlock);
|
||||||
mBfIRBuilder->SetInsertPoint(caseBlock);
|
mBfIRBuilder->SetInsertPoint(caseBlock);
|
||||||
|
@ -4921,6 +4945,7 @@ void BfModule::Visit(BfSwitchStatement* switchStmt)
|
||||||
if (switchStmt->mDefaultCase != NULL)
|
if (switchStmt->mDefaultCase != NULL)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, hadConstMatch);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true, hadConstMatch);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mCurMethodState->mCurScope->mInConstIgnore, true, hadConstMatch);
|
||||||
|
|
||||||
mBfIRBuilder->AddBlock(defaultBlock);
|
mBfIRBuilder->AddBlock(defaultBlock);
|
||||||
mBfIRBuilder->SetInsertPoint(defaultBlock);
|
mBfIRBuilder->SetInsertPoint(defaultBlock);
|
||||||
|
@ -5742,6 +5767,7 @@ void BfModule::Visit(BfWhileStatement* whileStmt)
|
||||||
if (isFalseLoop)
|
if (isFalseLoop)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> ignoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
||||||
|
SetAndRestoreValue<bool> prevInConstIgnore(mCurMethodState->mCurScope->mInConstIgnore, true);
|
||||||
VisitEmbeddedStatement(whileStmt->mEmbeddedStatement);
|
VisitEmbeddedStatement(whileStmt->mEmbeddedStatement);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -6693,6 +6719,8 @@ void BfModule::Visit(BfForEachStatement* forEachStmt)
|
||||||
{
|
{
|
||||||
if (!isVarEnumerator)
|
if (!isVarEnumerator)
|
||||||
AssertErrorState();
|
AssertErrorState();
|
||||||
|
|
||||||
|
mBfIRBuilder->CreateBr(endBB);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue