diff --git a/src/ir.cpp b/src/ir.cpp index 3184561ebc1c37706c3d2a4a86a0c466580c54f7..8c44363bbe6d272302b8ec1e20f7bb4aef09b46b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -18497,6 +18497,20 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns if (type_is_invalid(target->value.type)) return ira->codegen->builtin_types.entry_invalid; + if (target->value.type->id == TypeTableEntryIdComptimeInt) { + IrInstruction *casted_value = ir_implicit_cast(ira, target, dest_type); + if (type_is_invalid(casted_value->value.type)) + return ira->codegen->builtin_types.entry_invalid; + ir_link_new_instruction(casted_value, &instruction->base); + return casted_value->value.type; + } + + if (target->value.type->id != TypeTableEntryIdFloat && target->value.type->id != TypeTableEntryIdComptimeFloat) { + ir_add_error(ira, instruction->target, buf_sprintf("expected float type, found '%s'", + buf_ptr(&target->value.type->name))); + return ira->codegen->builtin_types.entry_invalid; + } + IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_type, CastOpFloatToInt, false); ir_link_new_instruction(result, &instruction->base); return dest_type; diff --git a/test/cases/cast.zig b/test/cases/cast.zig index 2b455ccc43710650dad64c472331e53948ff815b..94fbda7899971d7ca4e6b64b33b8cf27948b6397 100644 --- a/test/cases/cast.zig +++ b/test/cases/cast.zig @@ -356,6 +356,7 @@ fn testFloatToInts() void { expectFloatToInt(f32, 255.1, u8, 255); expectFloatToInt(f32, 127.2, i8, 127); expectFloatToInt(f32, -128.2, i8, -128); + expectFloatToInt(comptime_int, 1234, i16, 1234); } fn expectFloatToInt(comptime F: type, f: F, comptime I: type, i: I) void { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index cbca4bb7e3cfde92fc44812812c4d985ff657d73..00fc33d1225981ba8d986e99ffbdc987d601ad4c 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -1,6 +1,33 @@ const tests = @import("tests.zig"); pub fn addCases(cases: *tests.CompileErrorContext) void { + cases.add( + "non int passed to @intToFloat", + \\export fn entry() void { + \\ const x = @intToFloat(f32, 1.1); + \\} + , + ".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'", + ); + + cases.add( + "non float passed to @floatToInt", + \\export fn entry() void { + \\ const x = @floatToInt(i32, i32(54)); + \\} + , + ".tmp_source.zig:2:35: error: expected float type, found 'i32'", + ); + + cases.add( + "out of range comptime_int passed to @floatToInt", + \\export fn entry() void { + \\ const x = @floatToInt(i8, 200); + \\} + , + ".tmp_source.zig:2:31: error: integer value 200 cannot be implicitly casted to type 'i8'", + ); + cases.add( "load too many bytes from comptime reinterpreted pointer", \\export fn entry() void { @@ -486,15 +513,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { ".tmp_source.zig:2:20: error: return type cannot be opaque", ); - cases.add( - "non int passed to @intToFloat", - \\export fn entry() void { - \\ const x = @intToFloat(f32, 1.1); - \\} - , - ".tmp_source.zig:2:32: error: expected int type, found 'comptime_float'", - ); - cases.add( "use implicit casts to assign null to non-nullable pointer", \\export fn entry() void {