authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-28 23:32:19-04:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2021-06-08 20:58:30+03:00
log9ac6d2861466e03407dddebf47354034be9a136c
treeb615983d7ea908439044f8e242d940b45ce107bc
parentff0a15bb7a57370091898fde7bd53364c90252df

stage1: make `@truncate` to an integer type of different sign an error at comptime too


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,6 +19563,18 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc
19563 return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);19563 return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
19564 }19564 }
1956519565
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 if (instr_is_comptime(target)) {19578 if (instr_is_comptime(target)) {
19567 ZigValue *val = ir_resolve_const(ira, target, UndefBad);19579 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
19568 if (val == nullptr)19580 if (val == nullptr)
...@@ -19580,16 +19592,6 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc...@@ -19580,16 +19592,6 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc
19580 return result;19592 return result;
19581 }19593 }
1958219594
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 return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target);19595 return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target);
19594}19596}
1959519597
test/behavior/truncate.zig+25-4
...@@ -24,13 +24,34 @@ test "truncate.u0.var" {...@@ -24,13 +24,34 @@ test "truncate.u0.var" {
24 try expect(z == 0);24 try expect(z == 0);
25}25}
2626
27test "truncate sign mismatch but comptime known so it works anyway" {27test "truncate i0 to larger integer allowed and has comptime known result" {
28 const x: u32 = 10;28 var x: i0 = 0;
29 var result = @truncate(i8, x);29 const y = @truncate(i8, x);
30 try expect(result == 10);30 comptime try expect(y == 0);
31}
32
33test "truncate.i0.literal" {
34 var z = @truncate(i0, 0);
35 try expect(z == 0);
36}
37
38test "truncate.i0.const" {
39 const c0: isize = 0;
40 var z = @truncate(i0, c0);
41 try expect(z == 0);
42}
43
44test "truncate.i0.var" {
45 var d: i8 = 2;
46 var z = @truncate(i0, d);
47 try expect(z == 0);
31}48}
3249
33test "truncate on comptime integer" {50test "truncate on comptime integer" {
34 var x = @truncate(u16, 9999);51 var x = @truncate(u16, 9999);
35 try expect(x == 9999);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,14 +6031,27 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6031 });6031 });
60326032
6033 cases.add("truncate sign mismatch",6033 cases.add("truncate sign mismatch",
6034 \\fn f() i8 {6034 \\export fn entry1() i8 {
6035 \\ var x: u32 = 10;6035 \\ var x: u32 = 10;
6036 \\ return @truncate(i8, x);6036 \\ return @truncate(i8, x);
6037 \\}6037 \\}
6038 \\6038 \\export fn entry2() u8 {
6039 \\export fn entry() usize { return @sizeOf(@TypeOf(f)); }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 , &[_][]const u8{6050 , &[_][]const u8{
6041 "tmp.zig:3:26: error: expected signed integer type, found 'u32'",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 });
60436056
6044 cases.add("try in function with non error return type",6057 cases.add("try in function with non error return type",