fix(0112): out-of-range int literals error instead of silently wrapping
checkIntLiteralFits range-checks a literal against its integer target (builtins + custom widths via intLiteralRange; width-64 types skip — every representable literal is a legal bit pattern there) and diagnoses with the type's range and an xx/cast hint. Wired into the .int_literal arm (covers decls, assignments, call args, struct-literal fields), lowerStructConstant, and globalInitValue. A negated literal now folds to a single constant so -128 range-checks as -128 rather than as an out-of-range +128 intermediate. An explicit xx operand skips the check — truncation stays available on request (cast(T) was already exempt: its value arg lowers without the target). examples/0300-closures-lambda.sx pinned 133 wrapping to -3 through an s3 param — the exact class this outlaws; updated to a fitting value. Found during the fix and filed separately: issue 0113 (negated-literal global initializers rejected as non-constant; pre-existing). Regressions: examples/1156-diagnostics-int-literal-out-of-range.sx, examples/0174-types-int-literal-boundaries.sx.
This commit is contained in:
22
examples/0174-types-int-literal-boundaries.sx
Normal file
22
examples/0174-types-int-literal-boundaries.sx
Normal file
@@ -0,0 +1,22 @@
|
||||
// Boundary and exemption cases for the int-literal fits-check: extreme
|
||||
// in-range values compile (incl. negated literals via the constant fold);
|
||||
// width-64 types accept any representable literal; explicit `xx` / `cast`
|
||||
// still truncate on request; literal call args check against param types.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
clamp_s8 :: (v: s8) -> s8 { v }
|
||||
|
||||
main :: () {
|
||||
a : s8 = -128;
|
||||
b : s8 = 127;
|
||||
c : u8 = 0;
|
||||
d : u8 = 255;
|
||||
e : u64 = 0x7FFFFFFFFFFFFFFF;
|
||||
f : u32 = 0xFFFFFFFF;
|
||||
g : s16 = -32768;
|
||||
h : s8 = xx 300; // explicit truncation stays legal
|
||||
i := cast(s8) 300; // cast form too
|
||||
j : s8 = clamp_s8(-5);
|
||||
print("{} {} {} {} {} {} {} {} {} {}\n", a, b, c, d, e, f, g, h, i, j);
|
||||
}
|
||||
@@ -5,5 +5,5 @@ main :: () {
|
||||
s
|
||||
}
|
||||
|
||||
print("{}\n", fx(133));
|
||||
print("{}\n", fx(-3));
|
||||
}
|
||||
|
||||
12
examples/1156-diagnostics-int-literal-out-of-range.sx
Normal file
12
examples/1156-diagnostics-int-literal-out-of-range.sx
Normal file
@@ -0,0 +1,12 @@
|
||||
// An integer literal that does not fit its integer target type is a
|
||||
// compile error (no silent wrap): both faces diagnosed in one run.
|
||||
// Regression (issue 0112): `x : s8 = 300` bound 44, `y : u8 = 256` bound 0.
|
||||
|
||||
#import "modules/std.sx";
|
||||
|
||||
main :: () {
|
||||
x : s8 = 300;
|
||||
print("x: {}\n", x);
|
||||
y : u8 = 256;
|
||||
print("y: {}\n", y);
|
||||
}
|
||||
1
examples/expected/0174-types-int-literal-boundaries.exit
Normal file
1
examples/expected/0174-types-int-literal-boundaries.exit
Normal file
@@ -0,0 +1 @@
|
||||
0
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
-128 127 0 255 9223372036854775807 4294967295 -32768 44 44 -5
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,11 @@
|
||||
error: integer literal 300 does not fit in s8 (range -128..127) — use an explicit `xx` / `cast` to truncate
|
||||
--> examples/1156-diagnostics-int-literal-out-of-range.sx:8:14
|
||||
|
|
||||
8 | x : s8 = 300;
|
||||
| ^^^
|
||||
|
||||
error: integer literal 256 does not fit in u8 (range 0..255) — use an explicit `xx` / `cast` to truncate
|
||||
--> examples/1156-diagnostics-int-literal-out-of-range.sx:10:14
|
||||
|
|
||||
10 | y : u8 = 256;
|
||||
| ^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user