From 89c98e200166aa3e4f5b41859f450d1307216191 Mon Sep 17 00:00:00 2001 From: Jay Petacat Date: Wed, 21 Jan 2026 22:57:32 -0700 Subject: [PATCH] Sema: fix integer coercion to `c_longdouble` This is a follow-up to PR #30053 / commit 484cc15366. The code previously did not handle `c_longdouble`, whose size depends on the target. A `floatSignificandBits` helper function and a smoke test were added. Also added the missing max int value to the exhaustive `f16` test cases. --- src/Sema.zig | 10 +--------- src/Type.zig | 12 ++++++++++++ test/behavior/cast.zig | 3 +++ ...nt_to_float.zig => coerce_large_int_to_float.zig} | 0 4 files changed, 16 insertions(+), 9 deletions(-) rename test/cases/compile_errors/{coerce_int_to_float.zig => coerce_large_int_to_float.zig} (100%) diff --git a/src/Sema.zig b/src/Sema.zig index f2c52697b4..f9e343f549 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 841ca38b0e..a6bdb6ff82 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 6515df5e2f..eca43fea44 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_large_int_to_float.zig similarity index 100% rename from test/cases/compile_errors/coerce_int_to_float.zig rename to test/cases/compile_errors/coerce_large_int_to_float.zig