diff --git a/src/Sema.zig b/src/Sema.zig index f2c52697b420eeca9674ed4f2e5f75060a67809a..f9e343f549ac550ab1560091d5d34f481ce2a014 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -27774,15 +27774,7 @@ fn coerceExtra( } const int_info = inst_ty.intInfo(zcu); const int_precision = int_info.bits - @intFromBool(int_info.signedness == .signed); - const float_precision: u8 = switch (dest_ty.toIntern()) { - .f16_type => 11, - .f32_type => 24, - .f64_type => 53, - .f80_type => 64, - .f128_type => 113, - else => unreachable, - }; - if (int_precision <= float_precision) { + if (int_precision <= dest_ty.floatSignificandBits(target)) { try sema.requireRuntimeBlock(block, inst_src, null); return block.addTyOp(.float_from_int, dest_ty, inst); } diff --git a/src/Type.zig b/src/Type.zig index 841ca38b0e536b79ca44817eb55941b864ac3f56..a6bdb6ff822f15235963826e385b9ebc855aadd4 100644 --- a/src/Type.zig +++ b/src/Type.zig @@ -1936,6 +1936,18 @@ pub fn floatBits(ty: Type, target: *const Target) u16 { }; } +/// Asserts the type is a fixed-size float or comptime_float. +pub fn floatSignificandBits(ty: Type, target: *const Target) u16 { + return switch (ty.floatBits(target)) { + 16 => 11, + 32 => 24, + 64 => 53, + 80 => 64, + 128 => 113, + else => unreachable, + }; +} + /// Asserts the type is a function or a function pointer. pub fn fnReturnType(ty: Type, zcu: *const Zcu) Type { return Type.fromInterned(zcu.intern_pool.funcTypeReturnType(ty.toIntern())); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index 6515df5e2f8f87ed87fa33206b4e388d201b5478..eca43fea44bf3e23a8e6c518a563c5f6f5e12452 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -175,6 +175,7 @@ test "type coercion from int to float" { var int: Int = std.math.minInt(Int); while (int < std.math.maxInt(Int)) : (int += 1) try value(Float, int); + try value(Float, int); // max } // Check that the min and max values of the integer type can safely be @@ -202,6 +203,8 @@ test "type coercion from int to float" { try check.edgeValues(f128, u113); try check.edgeValues(f128, i114); + try check.value(c_longdouble, @as(u1, 0)); // Smoke test - size varies by target. + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; diff --git a/test/cases/compile_errors/coerce_int_to_float.zig b/test/cases/compile_errors/coerce_int_to_float.zig deleted file mode 100644 index d1bf6eb2be077f38245412ee237a9c84f8291fbe..0000000000000000000000000000000000000000 --- a/test/cases/compile_errors/coerce_int_to_float.zig +++ /dev/null @@ -1,52 +0,0 @@ -// Test that integer types above a certain size will not coerce to a float. - -fn testCoerce(Float: type, Int: type) void { - var i: Int = 0; - _ = &i; - _ = @as(Float, i); -} - -export fn entry() void { - testCoerce(f16, u11); // Okay - testCoerce(f16, u12); // Too big - - testCoerce(f16, i12); - testCoerce(f16, i13); - - testCoerce(f32, u24); - testCoerce(f32, u25); - - testCoerce(f32, i25); - testCoerce(f32, i26); - - testCoerce(f64, u53); - testCoerce(f64, u54); - - testCoerce(f64, i54); - testCoerce(f64, i55); - - testCoerce(f80, u64); - testCoerce(f80, u65); - - testCoerce(f80, i65); - testCoerce(f80, i66); - - testCoerce(f128, u113); - testCoerce(f128, u114); - - testCoerce(f128, i114); - testCoerce(f128, i115); -} - -// error -// -// :6:20: error: expected type 'f128', found 'i115' -// :6:20: error: expected type 'f128', found 'u114' -// :6:20: error: expected type 'f16', found 'i13' -// :6:20: error: expected type 'f16', found 'u12' -// :6:20: error: expected type 'f32', found 'i26' -// :6:20: error: expected type 'f32', found 'u25' -// :6:20: error: expected type 'f64', found 'i55' -// :6:20: error: expected type 'f64', found 'u54' -// :6:20: error: expected type 'f80', found 'i66' -// :6:20: error: expected type 'f80', found 'u65' diff --git a/test/cases/compile_errors/coerce_large_int_to_float.zig b/test/cases/compile_errors/coerce_large_int_to_float.zig new file mode 100644 index 0000000000000000000000000000000000000000..d1bf6eb2be077f38245412ee237a9c84f8291fbe --- /dev/null +++ b/test/cases/compile_errors/coerce_large_int_to_float.zig @@ -0,0 +1,52 @@ +// Test that integer types above a certain size will not coerce to a float. + +fn testCoerce(Float: type, Int: type) void { + var i: Int = 0; + _ = &i; + _ = @as(Float, i); +} + +export fn entry() void { + testCoerce(f16, u11); // Okay + testCoerce(f16, u12); // Too big + + testCoerce(f16, i12); + testCoerce(f16, i13); + + testCoerce(f32, u24); + testCoerce(f32, u25); + + testCoerce(f32, i25); + testCoerce(f32, i26); + + testCoerce(f64, u53); + testCoerce(f64, u54); + + testCoerce(f64, i54); + testCoerce(f64, i55); + + testCoerce(f80, u64); + testCoerce(f80, u65); + + testCoerce(f80, i65); + testCoerce(f80, i66); + + testCoerce(f128, u113); + testCoerce(f128, u114); + + testCoerce(f128, i114); + testCoerce(f128, i115); +} + +// error +// +// :6:20: error: expected type 'f128', found 'i115' +// :6:20: error: expected type 'f128', found 'u114' +// :6:20: error: expected type 'f16', found 'i13' +// :6:20: error: expected type 'f16', found 'u12' +// :6:20: error: expected type 'f32', found 'i26' +// :6:20: error: expected type 'f32', found 'u25' +// :6:20: error: expected type 'f64', found 'i55' +// :6:20: error: expected type 'f64', found 'u54' +// :6:20: error: expected type 'f80', found 'i66' +// :6:20: error: expected type 'f80', found 'u65'