commit a9d3768bec7024506c16493bad34b3d2c80bcc4d
parent 633f10d43ff4bcaf6720e5905f71d1392aecb136
Author: Bor Grošelj Simić <bgs@turminal.net>
Date: Sun, 5 Feb 2023 15:51:34 +0100
lex: error out on overflowing integer exponents
References: https://todo.sr.ht/~sircmpwn/hare/737
Signed-off-by: Bor Grošelj Simić <bgs@turminal.net>
Diffstat:
2 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/src/lex.c b/src/lex.c
@@ -297,6 +297,25 @@ lex_name(struct lexer *lexer, struct token *out)
return out->token;
}
+static uintmax_t
+compute_exp(uintmax_t n, int exponent, bool _signed, struct location *loc)
+{
+ if (n == 0) {
+ return 0;
+ }
+ for (int i = 0; i < exponent; i++) {
+ uintmax_t old = n;
+ n *= 10;
+ if (n / 10 != old) {
+ error(loc, "Integer literal overflow");
+ }
+ }
+ if (_signed && n > (uintmax_t)INT64_MIN) {
+ error(loc, "Integer literal overflow");
+ }
+ return n;
+}
+
static uint32_t
lex_literal(struct lexer *lexer, struct token *out)
{
@@ -488,16 +507,12 @@ finalize:
case STORAGE_UINT:
case STORAGE_U64:
case STORAGE_SIZE:
- out->uval = strtoumax(lexer->buf, NULL, base);
- for (intmax_t i = 0; i < exponent; i++) {
- out->uval *= 10;
- }
+ out->uval = compute_exp(strtoumax(lexer->buf, NULL, base),
+ exponent, false, &out->loc);
break;
case STORAGE_ICONST:
- out->uval = strtoumax(lexer->buf, NULL, base);
- for (intmax_t i = 0; i < exponent; i++) {
- out->uval *= 10;
- }
+ out->uval = compute_exp(strtoumax(lexer->buf, NULL, base),
+ exponent, false, &out->loc);
if (out->uval > (uintmax_t)INT64_MAX) {
out->storage = STORAGE_U64;
break;
@@ -508,18 +523,13 @@ finalize:
case STORAGE_I32:
case STORAGE_INT:
case STORAGE_I64:
- out->uval = strtoumax(lexer->buf, NULL, base);
- for (intmax_t i = 0; i < exponent; i++) {
- out->uval *= 10;
- }
+ out->uval = compute_exp(strtoumax(lexer->buf, NULL, base),
+ exponent, true, &out->loc);
if (out->uval == (uintmax_t)INT64_MIN) {
// XXX: Hack
out->ival = INT64_MIN;
- break;
- }
- out->ival = strtoimax(lexer->buf, NULL, base);
- for (intmax_t i = 0; i < exponent; i++) {
- out->ival *= 10;
+ } else {
+ out->ival = (intmax_t)out->uval;
}
break;
case STORAGE_F32:
diff --git a/tests/00-constants.ha b/tests/00-constants.ha
@@ -137,7 +137,7 @@ fn aggregates() void = {
u2arr as [3]u8;
};
-export fn main() void = {
+fn basics() void = {
let i1 = 13, i2 = 13i, i3 = 13i8, i4 = 13i16, i5 = 13i32, i6 = 13i64;
let u1 = 13u, u2 = 13z, u3 = 13u8, u4 = 13u16, u5 = 13u32, u6 = 13u64;
let n1 = -13, n2 = -13u;
@@ -149,9 +149,15 @@ export fn main() void = {
r15 = '\U12345678';
let f1 = 1.0, f2 = 1f32, f3 = 1.0e2, f4 = 1.0f64;
let f5 = 1.23e+45, f6 = 9.87e-65, f7 = 1e-7, f8 = 5.0e-324;
+ let ie1 = 1e5i;
+
+ assert(compile("let x: u64 = 1e100;") as exited != EXIT_SUCCESS);
+};
+export fn main() void = {
// The interaction between constants and result type reduction is tested
// in 30-reduction.c
+ basics();
assignment();
aggregates();
};