| author | |
| committer | |
| log | 503b85a1b0cd3d180987053eba71c449a6389e1b |
| tree | cec83e12c4e6066646148ed785043ff0161bc726 |
| parent | 0c25ff81a388ea1c03721562b0abea7e4dc43cbd |
3 files changed, 53 insertions(+), 17 deletions(-)
src/stage1/ir.cpp+12-10| ... | ... | @@ -19563,6 +19563,18 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc |
| 19563 | 19563 | return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type); |
| 19564 | 19564 | } |
| 19565 | 19565 | |
| 19566 | if (src_type->id != ZigTypeIdComptimeInt) { | |
| 19567 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | |
| 19568 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | |
| 19569 | ir_add_error(ira, &target->base, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); | |
| 19570 | return ira->codegen->invalid_inst_gen; | |
| 19571 | } else if (src_type->data.integral.bit_count > 0 && src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { | |
| 19572 | ir_add_error(ira, &target->base, buf_sprintf("type '%s' has fewer bits than destination type '%s'", | |
| 19573 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | |
| 19574 | return ira->codegen->invalid_inst_gen; | |
| 19575 | } | |
| 19576 | } | |
| 19577 | ||
| 19566 | 19578 | if (instr_is_comptime(target)) { |
| 19567 | 19579 | ZigValue *val = ir_resolve_const(ira, target, UndefBad); |
| 19568 | 19580 | if (val == nullptr) |
| ... | ... | @@ -19580,16 +19592,6 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc |
| 19580 | 19592 | return result; |
| 19581 | 19593 | } |
| 19582 | 19594 | |
| 19583 | if (src_type->data.integral.is_signed != dest_type->data.integral.is_signed) { | |
| 19584 | const char *sign_str = dest_type->data.integral.is_signed ? "signed" : "unsigned"; | |
| 19585 | ir_add_error(ira, &target->base, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); | |
| 19586 | return ira->codegen->invalid_inst_gen; | |
| 19587 | } else if (src_type->data.integral.bit_count < dest_type->data.integral.bit_count) { | |
| 19588 | ir_add_error(ira, &target->base, buf_sprintf("type '%s' has fewer bits than destination type '%s'", | |
| 19589 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | |
| 19590 | return ira->codegen->invalid_inst_gen; | |
| 19591 | } | |
| 19592 | ||
| 19593 | 19595 | return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target); |
| 19594 | 19596 | } |
| 19595 | 19597 |
test/behavior/truncate.zig+25-4| ... | ... | @@ -24,13 +24,34 @@ test "truncate.u0.var" { |
| 24 | 24 | try expect(z == 0); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | test "truncate sign mismatch but comptime known so it works anyway" { | |
| 28 | const x: u32 = 10; | |
| 29 | var result = @truncate(i8, x); | |
| 30 | try expect(result == 10); | |
| 27 | test "truncate i0 to larger integer allowed and has comptime known result" { | |
| 28 | var x: i0 = 0; | |
| 29 | const y = @truncate(i8, x); | |
| 30 | comptime try expect(y == 0); | |
| 31 | } | |
| 32 | ||
| 33 | test "truncate.i0.literal" { | |
| 34 | var z = @truncate(i0, 0); | |
| 35 | try expect(z == 0); | |
| 36 | } | |
| 37 | ||
| 38 | test "truncate.i0.const" { | |
| 39 | const c0: isize = 0; | |
| 40 | var z = @truncate(i0, c0); | |
| 41 | try expect(z == 0); | |
| 42 | } | |
| 43 | ||
| 44 | test "truncate.i0.var" { | |
| 45 | var d: i8 = 2; | |
| 46 | var z = @truncate(i0, d); | |
| 47 | try expect(z == 0); | |
| 31 | 48 | } |
| 32 | 49 | |
| 33 | 50 | test "truncate on comptime integer" { |
| 34 | 51 | var x = @truncate(u16, 9999); |
| 35 | 52 | try expect(x == 9999); |
| 53 | var y = @truncate(u16, -21555); | |
| 54 | try expect(y == 0xabcd); | |
| 55 | var z = @truncate(i16, -65537); | |
| 56 | try expect(z == -1); | |
| 36 | 57 | } |
test/compile_errors.zig+16-3| ... | ... | @@ -6031,14 +6031,27 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 6031 | 6031 | }); |
| 6032 | 6032 | |
| 6033 | 6033 | cases.add("truncate sign mismatch", |
| 6034 | \\fn f() i8 { | |
| 6034 | \\export fn entry1() i8 { | |
| 6035 | 6035 | \\ var x: u32 = 10; |
| 6036 | 6036 | \\ return @truncate(i8, x); |
| 6037 | 6037 | \\} |
| 6038 | \\ | |
| 6039 | \\export fn entry() usize { return @sizeOf(@TypeOf(f)); } | |
| 6038 | \\export fn entry2() u8 { | |
| 6039 | \\ var x: i32 = -10; | |
| 6040 | \\ return @truncate(u8, x); | |
| 6041 | \\} | |
| 6042 | \\export fn entry3() i8 { | |
| 6043 | \\ comptime var x: u32 = 10; | |
| 6044 | \\ return @truncate(i8, x); | |
| 6045 | \\} | |
| 6046 | \\export fn entry4() u8 { | |
| 6047 | \\ comptime var x: i32 = -10; | |
| 6048 | \\ return @truncate(u8, x); | |
| 6049 | \\} | |
| 6040 | 6050 | , &[_][]const u8{ |
| 6041 | 6051 | "tmp.zig:3:26: error: expected signed integer type, found 'u32'", |
| 6052 | "tmp.zig:7:26: error: expected unsigned integer type, found 'i32'", | |
| 6053 | "tmp.zig:11:26: error: expected signed integer type, found 'u32'", | |
| 6054 | "tmp.zig:15:26: error: expected unsigned integer type, found 'i32'", | |
| 6042 | 6055 | }); |
| 6043 | 6056 | |
| 6044 | 6057 | cases.add("try in function with non error return type", |