harec

[hare] Hare compiler, written in C11 for POSIX OSs
Log | Files | Refs | README | LICENSE

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:
Msrc/lex.c | 44+++++++++++++++++++++++++++-----------------
Mtests/00-constants.ha | 8+++++++-
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(); };