Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions source/compiler-core/slang-lexer-diagnostic-defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ DIAGNOSTIC(

DIAGNOSTIC(10011, Error, unexpectedEndOfInput, "unexpected end of input")

DIAGNOSTIC(
10012,
Error,
integerLiteralTooLargeForAnyType,
"integer literal is too large to be represented in any integer type")

#undef DIAGNOSTIC
19 changes: 17 additions & 2 deletions source/compiler-core/slang-lexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -725,27 +725,37 @@ static int _readOptionalBase(char const** ioCursor)

IntegerLiteralValue getIntegerLiteralValue(
Token const& token,
DiagnosticSink* sink,
Comment thread
jkwak-work marked this conversation as resolved.
UnownedStringSlice* outSuffix,
bool* outIsDecimalBase)
bool* outIsDecimalBase,
bool* outHasOverflowed)
{
IntegerLiteralValue value = 0;
uint64_t value = 0;

const UnownedStringSlice content = token.getContent();

char const* cursor = content.begin();
char const* end = content.end();

int base = _readOptionalBase(&cursor);
bool hasOverflowed = false;

for (;;)
{
int digit = _maybeReadDigit(&cursor, base);
if (digit < 0)
break;

if (value > (UINT64_MAX - digit) / base)
hasOverflowed = true;
value = value * base + digit;
}

if (hasOverflowed)
{
diagnose(sink, token.getLoc(), LexerDiagnostics::integerLiteralTooLargeForAnyType);
}

if (outSuffix)
{
*outSuffix = UnownedStringSlice(cursor, end);
Expand All @@ -756,6 +766,11 @@ IntegerLiteralValue getIntegerLiteralValue(
*outIsDecimalBase = (base == 10);
}

if (outHasOverflowed)
{
*outHasOverflowed = hasOverflowed;
}

return value;
}

Expand Down
4 changes: 3 additions & 1 deletion source/compiler-core/slang-lexer.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ typedef double FloatingPointLiteralValue;

IntegerLiteralValue getIntegerLiteralValue(
Token const& token,
DiagnosticSink* sink,
UnownedStringSlice* outSuffix = 0,
bool* outIsDecimalBase = 0);
bool* outIsDecimalBase = 0,
bool* outHasOverflowed = 0);
FloatingPointLiteralValue getFloatingPointLiteralValue(
Token const& token,
UnownedStringSlice* outSuffix = 0);
Expand Down
2 changes: 1 addition & 1 deletion source/slang/slang-check-expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4422,7 +4422,7 @@ Expr* SemanticsExprVisitor::visitTypeCastExpr(TypeCastExpr* expr)
auto arg = expr->arguments[0];
if (auto intLitArg = as<IntegerLiteralExpr>(arg))
{
if (getIntegerLiteralValue(intLitArg->token) == 0)
if (getIntegerLiteralValue(intLitArg->token, getSink()) == 0)
{
// At this point we have confirmed that the cast
// has the right form, so we want to apply our special case.
Expand Down
4 changes: 2 additions & 2 deletions source/slang/slang-lower-to-ir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11109,7 +11109,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
{
getBuilder()->addRequireGLSLVersionDecoration(
inst,
Int(getIntegerLiteralValue(versionMod->versionNumberToken)));
Int(getIntegerLiteralValue(versionMod->versionNumberToken, getSink())));
}
for (auto versionMod : decl->getModifiersOfType<RequiredSPIRVVersionModifier>())
{
Expand Down Expand Up @@ -12146,7 +12146,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
else if (auto versionMod = as<RequiredGLSLVersionModifier>(modifier))
getBuilder()->addRequireGLSLVersionDecoration(
irFunc,
Int(getIntegerLiteralValue(versionMod->versionNumberToken)));
Int(getIntegerLiteralValue(versionMod->versionNumberToken, getSink())));
else if (auto spvVersion = as<RequiredSPIRVVersionModifier>(modifier))
getBuilder()->addRequireSPIRVVersionDecoration(irFunc, spvVersion->version);
else if (auto wgslExtensionMod = as<RequiredWGSLExtensionModifier>(modifier))
Expand Down
18 changes: 14 additions & 4 deletions source/slang/slang-parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3311,7 +3311,7 @@ static Modifier* ParseSemantic(Parser* parser)
BitFieldModifier* bitWidthMod = parser->astBuilder->create<BitFieldModifier>();
parser->FillPosition(bitWidthMod);
const auto token = parser->tokenReader.advanceToken();
bitWidthMod->width = getIntegerLiteralValue(token);
bitWidthMod->width = getIntegerLiteralValue(token, parser->sink);
return bitWidthMod;
}
else if (parser->LookAheadToken(TokenType::CompletionRequest))
Expand Down Expand Up @@ -7752,7 +7752,13 @@ static Expr* parseAtomicExpr(Parser* parser)

UnownedStringSlice suffix;
bool isDecimalBase;
IntegerLiteralValue value = getIntegerLiteralValue(token, &suffix, &isDecimalBase);
bool hasOverflowed;
IntegerLiteralValue value = getIntegerLiteralValue(
token,
parser->sink,
&suffix,
&isDecimalBase,
&hasOverflowed);

// Look at any suffix on the value
char const* suffixCursor = suffix.begin();
Expand Down Expand Up @@ -7832,14 +7838,18 @@ static Expr* parseAtomicExpr(Parser* parser)
suffixBaseType = BaseType::Int;
}
}
else
else if (!hasOverflowed)
{
suffixBaseType = _determineNonSuffixedIntegerLiteralType(
value,
isDecimalBase,
&token,
parser->sink);
}
else
{
suffixBaseType = BaseType::UInt64;
}

value = _fixIntegerLiteral(suffixBaseType, value, &token, parser->sink);

Expand Down Expand Up @@ -8395,7 +8405,7 @@ static std::optional<SPIRVAsmOperand> parseSPIRVAsmOperand(Parser* parser)
else if (parser->LookAheadToken(TokenType::IntegerLiteral))
{
const auto tok = parser->ReadToken();
const auto v = getIntegerLiteralValue(tok);
const auto v = getIntegerLiteralValue(tok, parser->sink);
if (v < 0 || v > 0xffffffff)
parser->diagnose(tok, Diagnostics::spirvOperandRange);
return SPIRVAsmOperand{SPIRVAsmOperand::Literal, tok, nullptr, {}, SpvWord(v)};
Expand Down
14 changes: 14 additions & 0 deletions tests/diagnostics/int-literal-errors.slang
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//DIAGNOSTIC_TEST:SIMPLE:

void foo()
{
// Ok.
uint64_t ok1 = 18446744073709551615U; // UINT64_MAX
uint64_t ok2 = 0xffffffffffffffffU; // UINT64_MAX

// Error, integer literal is too large to be represented in any integer type.
uint64_t tooLargeForAnyType1 = 18446744073709551616; // UINT64_MAX + 1
uint64_t tooLargeForAnyType2 = 184467440737095516150; // UINT64_MAX * 10
uint64_t tooLargeForAnyType3 = 0x10000000000000000; // UINT64_MAX + 1
uint64_t tooLargeForAnyType4 = 0xffffffffffffffff0; // UINT64_MAX * 16
}
17 changes: 17 additions & 0 deletions tests/diagnostics/int-literal-errors.slang.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
result code = -1
standard error = {
tests/diagnostics/int-literal-errors.slang(10): error 10012: integer literal is too large to be represented in any integer type
uint64_t tooLargeForAnyType1 = 18446744073709551616; // UINT64_MAX + 1
^~~~~~~~~~~~~~~~~~~~
tests/diagnostics/int-literal-errors.slang(11): error 10012: integer literal is too large to be represented in any integer type
uint64_t tooLargeForAnyType2 = 184467440737095516150; // UINT64_MAX * 10
^~~~~~~~~~~~~~~~~~~~~
tests/diagnostics/int-literal-errors.slang(12): error 10012: integer literal is too large to be represented in any integer type
uint64_t tooLargeForAnyType3 = 0x10000000000000000; // UINT64_MAX + 1
^~~~~~~~~~~~~~~~~~~
tests/diagnostics/int-literal-errors.slang(13): error 10012: integer literal is too large to be represented in any integer type
uint64_t tooLargeForAnyType4 = 0xffffffffffffffff0; // UINT64_MAX * 16
^~~~~~~~~~~~~~~~~~~
}
standard output = {
}