authorgravatar for matthew.h.borkowski@gmail.comMatthew Borkowski <matthew.h.borkowski@gmail.com> 2021-05-28 23:32:19-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-06-08 12:27:22-07:00
log503b85a1b0cd3d180987053eba71c449a6389e1b
treecec83e12c4e6066646148ed785043ff0161bc726
parent0c25ff81a388ea1c03721562b0abea7e4dc43cbd

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
1956319563 return ir_implicit_cast2(ira, &instruction->target->base, target, dest_type);
1956419564 }
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
1956619578 if (instr_is_comptime(target)) {
1956719579 ZigValue *val = ir_resolve_const(ira, target, UndefBad);
1956819580 if (val == nullptr)
......@@ -19580,16 +19592,6 @@ static IrInstGen *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstSrcTrunc
1958019592 return result;
1958119593 }
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
1959319595 return ir_build_truncate_gen(ira, &instruction->base.base, dest_type, target);
1959419596}
1959519597
test/behavior/truncate.zig+25-4
......@@ -24,13 +24,34 @@ test "truncate.u0.var" {
2424 try expect(z == 0);
2525}
2626
27test "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);
27test "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
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);
3148}
3249
3350test "truncate on comptime integer" {
3451 var x = @truncate(u16, 9999);
3552 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);
3657}
test/compile_errors.zig+16-3
......@@ -6031,14 +6031,27 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
60316031 });
60326032
60336033 cases.add("truncate sign mismatch",
6034 \\fn f() i8 {
6034 \\export fn entry1() i8 {
60356035 \\ var x: u32 = 10;
60366036 \\ return @truncate(i8, x);
60376037 \\}
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 \\}
60406050 , &[_][]const u8{
60416051 "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'",
60426055 });
60436056
60446057 cases.add("try in function with non error return type",