mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-09 03:52:19 +02:00
Fixes for literal overflow detection
This commit is contained in:
parent
6a95cbb3b8
commit
a3b761ab26
6 changed files with 68 additions and 39 deletions
|
@ -3578,7 +3578,7 @@ void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
|
|||
if ((mExpectingType != NULL) && (mExpectingType->IsIntegral()) && (mExpectingType->IsChar() == IsCharType(variant.mTypeCode)))
|
||||
{
|
||||
auto primType = (BfPrimitiveType*)mExpectingType;
|
||||
if (mModule->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, variant.mInt64))
|
||||
if (mModule->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, variant.mUInt64))
|
||||
{
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, variant.mUInt64), mExpectingType);
|
||||
break;
|
||||
|
|
|
@ -7889,7 +7889,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
{
|
||||
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
|
||||
{
|
||||
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mInt64))
|
||||
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mUInt64))
|
||||
{
|
||||
if ((!ignoreErrors) && (PreFail()))
|
||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||
|
|
|
@ -2448,9 +2448,8 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
return;
|
||||
}
|
||||
|
||||
bool wasNeg = false;
|
||||
bool hadOverflow = false;
|
||||
int64 val = 0;
|
||||
uint64 val = 0;
|
||||
int numberBase = 10;
|
||||
int expVal = 0;
|
||||
int expSign = 0;
|
||||
|
@ -2460,8 +2459,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
int hexDigits = 0;
|
||||
if (c == '-')
|
||||
{
|
||||
wasNeg = true; //TODO: This never actually gets set any more (eaten as BfToken_Minus above). Move checks that use this to later in pipeline, then remove this
|
||||
c = mSrc[mSrcIdx++];
|
||||
BF_FATAL("Parsing error");
|
||||
}
|
||||
|
||||
val = c - '0';
|
||||
|
@ -2641,7 +2639,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
// This is actually a integer followed by an Int32 call (like 123.ToString)
|
||||
mSrcIdx -= 2;
|
||||
mTokenEnd = mSrcIdx;
|
||||
mLiteral.mInt64 = val;
|
||||
mLiteral.mUInt64 = val;
|
||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
return;
|
||||
|
@ -2669,26 +2667,23 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
{
|
||||
mTokenEnd = mSrcIdx - 1;
|
||||
mSrcIdx--;
|
||||
if (wasNeg)
|
||||
val = -val;
|
||||
|
||||
if ((numberBase == 0x10) &&
|
||||
((hexDigits >= 16) || ((hadSeps) && (hexDigits > 8)) || ((hadLeadingHexSep) && (hexDigits == 8))))
|
||||
{
|
||||
if (hexDigits > 16)
|
||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mLiteral.mInt64 = val;
|
||||
if ((val < 0) && (!wasNeg))
|
||||
mLiteral.mUInt64 = val;
|
||||
if (val >= 0x8000000000000000)
|
||||
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||
else
|
||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||
}
|
||||
else
|
||||
{
|
||||
mLiteral.mInt64 = val;
|
||||
mLiteral.mUInt64 = val;
|
||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||
|
||||
|
||||
if ((numberBase == 0x10) && (hexDigits == 7))
|
||||
mLiteral.mWarnType = BfWarning_BF4201_Only7Hex;
|
||||
if ((numberBase == 0x10) && (hexDigits == 9))
|
||||
|
@ -2699,7 +2694,12 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||
}
|
||||
else if ((val < -0x80000000LL) || (val > 0xFFFFFFFFLL))
|
||||
//else if ((val < -0x80000000LL) || (val > 0xFFFFFFFFLL))
|
||||
else if (val >= 0x8000000000000000)
|
||||
{
|
||||
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||
}
|
||||
else if (val > 0xFFFFFFFFLL)
|
||||
{
|
||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||
}
|
||||
|
@ -2709,7 +2709,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
return;
|
||||
}
|
||||
|
||||
int64 prevVal = val;
|
||||
uint64 prevVal = val;
|
||||
if ((c >= '0') && (c <= '9') && (c < '0' + numberBase))
|
||||
{
|
||||
if (numberBase == 0x10)
|
||||
|
@ -2732,8 +2732,6 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
|
||||
else if ((c == 'u') || (c == 'U'))
|
||||
{
|
||||
if (wasNeg)
|
||||
val = -val;
|
||||
if ((mSrc[mSrcIdx] == 'l') || (mSrc[mSrcIdx] == 'L'))
|
||||
{
|
||||
if (mSrc[mSrcIdx] == 'l')
|
||||
|
@ -2744,7 +2742,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mLiteral.mUInt64 = (uint64)val;
|
||||
if (hexDigits > 16)
|
||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
else if ((hadOverflow) || (wasNeg))
|
||||
else if (hadOverflow)
|
||||
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
return;
|
||||
|
@ -2752,7 +2750,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mTokenEnd = mSrcIdx;
|
||||
mLiteral.mTypeCode = BfTypeCode_UIntPtr;
|
||||
mLiteral.mUInt32 = (uint32)val;
|
||||
if ((hadOverflow) || (wasNeg) || ((uint64)val != (uint64)mLiteral.mUInt32))
|
||||
if ((hadOverflow) || ((uint64)val != (uint64)mLiteral.mUInt32))
|
||||
mPassInstance->FailAt("Value doesn't fit into uint32", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
return;
|
||||
|
@ -2761,8 +2759,6 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
{
|
||||
if (c == 'l')
|
||||
TokenFail("Uppercase 'L' required for int64");
|
||||
if (wasNeg)
|
||||
val = -val;
|
||||
if ((mSrc[mSrcIdx] == 'u') || (mSrc[mSrcIdx] == 'U'))
|
||||
{
|
||||
mSrcIdx++;
|
||||
|
@ -2771,7 +2767,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mLiteral.mUInt64 = (uint64)val;
|
||||
if (hexDigits > 16)
|
||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
else if ((hadOverflow) || (wasNeg))
|
||||
else if (hadOverflow)
|
||||
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
return;
|
||||
|
@ -2779,17 +2775,16 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
mTokenEnd = mSrcIdx;
|
||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||
mLiteral.mInt64 = (int64)val;
|
||||
|
||||
bool signMatched = true;
|
||||
if (val != 0)
|
||||
signMatched = (val < 0) == wasNeg;
|
||||
|
||||
if (val == 0x8000000000000000)
|
||||
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||
else if (val >= 0x8000000000000000)
|
||||
hadOverflow = true;
|
||||
if (numberBase == 0x10)
|
||||
{
|
||||
if (hexDigits > 16)
|
||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
}
|
||||
else if ((hadOverflow) || (!signMatched))
|
||||
else if (hadOverflow)
|
||||
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
return;
|
||||
|
@ -2814,16 +2809,13 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
|||
{
|
||||
mTokenEnd = mSrcIdx - 1;
|
||||
mSrcIdx--;
|
||||
if (wasNeg)
|
||||
val = -val;
|
||||
mLiteral.mInt64 = val;
|
||||
mLiteral.mUInt64 = val;
|
||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||
mSyntaxToken = BfSyntaxToken_Literal;
|
||||
TokenFail("Unexpected character while parsing number", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
//if ((val < 0) && (val != -0x8000000000000000))
|
||||
if ((uint64)prevVal > (uint64)val)
|
||||
hadOverflow = true;
|
||||
}
|
||||
|
|
|
@ -226,6 +226,7 @@ public:
|
|||
void SetSource(const char* data, int length);
|
||||
void MoveSource(const char* data, int length); // Takes ownership of data ptr
|
||||
void RefSource(const char* data, int length);
|
||||
void MakeNegative(uint64& val, bool& hadOverflow);
|
||||
void NextToken(int endIdx = -1, bool outerIsInterpolate = false);
|
||||
BfAstNode* CreateNode();
|
||||
|
||||
|
|
|
@ -2282,6 +2282,41 @@ bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, int64 value)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, uint64 value)
|
||||
{
|
||||
if (typeCode == BfTypeCode_IntPtr)
|
||||
typeCode = (mPtrSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64;
|
||||
if (typeCode == BfTypeCode_UIntPtr)
|
||||
typeCode = (mPtrSize == 4) ? BfTypeCode_UInt32 : BfTypeCode_UInt64;
|
||||
|
||||
if (value >= 0x8000000000000000)
|
||||
return typeCode == BfTypeCode_UInt64;
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case BfTypeCode_Int8:
|
||||
return (value < 0x80);
|
||||
case BfTypeCode_Int16:
|
||||
return (value < 0x8000);
|
||||
case BfTypeCode_Int32:
|
||||
return (value < 0x80000000LL);
|
||||
case BfTypeCode_Int64:
|
||||
return true;
|
||||
|
||||
case BfTypeCode_UInt8:
|
||||
return (value < 0x100);
|
||||
case BfTypeCode_UInt16:
|
||||
return (value < 0x10000);
|
||||
case BfTypeCode_UInt32:
|
||||
return (value < 0x100000000LL);
|
||||
case BfTypeCode_UInt64:
|
||||
return true;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
BfParser* BfSystem::CreateParser(BfProject* bfProject)
|
||||
{
|
||||
AutoCrit crit(mDataLock);
|
||||
|
|
|
@ -1610,6 +1610,7 @@ public:
|
|||
|
||||
void CreateBasicTypes();
|
||||
bool DoesLiteralFit(BfTypeCode typeCode, int64 value);
|
||||
bool DoesLiteralFit(BfTypeCode typeCode, uint64 value);
|
||||
BfParser* CreateParser(BfProject* bfProject);
|
||||
BfCompiler* CreateCompiler(bool isResolveOnly);
|
||||
BfProject* GetProject(const StringImpl& projName);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue