Merge pull request #7251 from kalsprite/s003

Validate floating-point array counts as integers
This commit is contained in:
Jeroen van Rijn
2026-08-08 00:28:04 +02:00
committed by GitHub
3 changed files with 39 additions and 9 deletions

View File

@@ -2846,9 +2846,14 @@ gb_internal i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
}
Type *type = core_type(o->type);
if (is_type_untyped(type) || is_type_integer(type)) {
if (o->value.kind == ExactValue_Integer) {
BigInt count = o->value.value_integer;
if (big_int_is_neg(&o->value.value_integer)) {
ExactValue value = o->value;
if (value.kind == ExactValue_Float) {
// NOTE: an integral float is a valid count, but it must be range checked as an integer
value = exact_value_to_integer(value);
}
if (value.kind == ExactValue_Integer) {
BigInt count = value.value_integer;
if (big_int_is_neg(&count)) {
gbAllocator a = heap_allocator();
String str = big_int_to_string(a, &count);
error(e, "Invalid negative array count, %.*s", LIT(str));
@@ -2864,12 +2869,6 @@ gb_internal i64 check_array_count(CheckerContext *ctx, Operand *o, Ast *e) {
error(e, "Array count too large, %.*s", LIT(str));
gb_free(a, str.text);
return 0;
} else if (o->value.kind == ExactValue_Float) {
u64 u = cast(u64)o->value.value_float;
f64 f = cast(f64)u;
if (f == o->value.value_float) {
return u;
}
}
}

View File

@@ -419,6 +419,12 @@ gb_internal ExactValue exact_value_to_integer(ExactValue v) {
case ExactValue_Integer:
return v;
case ExactValue_Float: {
f64 const min = cast(f64)I64_MIN; // -2^63
f64 const max = -min; // 2^63, one past I64_MAX
// NOTE: the conversion below is undefined outside of this range, NaN included
if (!(v.value_float >= min && v.value_float < max)) {
break;
}
i64 i = cast(i64)v.value_float;
f64 f = cast(f64)i;
if (f == v.value_float) {

View File

@@ -0,0 +1,25 @@
package test_internal
import "core:testing"
@(test)
array_count_from_integral_float :: proc(t: ^testing.T) {
testing.expect_value(t, len([3.0]u8{}), 3)
testing.expect_value(t, len([0.0]u8{}), 0)
testing.expect_value(t, size_of([3.0]u32), 12)
// folded constant expressions
Halved :: 6.0 / 2.0
Summed :: 1.5 + 1.5
testing.expect_value(t, len([Halved]u8{}), 3)
testing.expect_value(t, len([Summed]u8{}), 3)
// NOTE: keep below one BigInt limb: 2^28 on windows, 2^60 on linux
testing.expect_value(t, len([65536.0]struct{}{}), 1 << 16)
testing.expect_value(t, size_of(matrix[2.0, 3.0]f32), 24)
testing.expect_value(t, size_of(#simd[4.0]u8), 4)
Sparse :: [2.0]u8
testing.expect_value(t, len(Sparse{1, 2}), 2)
}