authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-16 17:04:35-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-16 17:04:35-04:00
log9851a943ed0360433c9612449ed065a6800adc51
treedcf15bcb1dd31da8ba975dd2594d7a89f5ca46ae
parentf37506391795353bbb87f49b73cf0f82ad9e2c17

add compile error for compile-time integer cast truncating bits

closes #371

3 files changed, 30 insertions(+), 6 deletions(-)

src/ir.cpp+14-6
......@@ -7053,12 +7053,20 @@ static IrInstruction *ir_analyze_widen_or_shorten(IrAnalyze *ira, IrInstruction
70537053 ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
70547054 if (!val)
70557055 return ira->codegen->invalid_instruction;
7056 if (val->data.x_bignum.is_negative && wanted_type->id == TypeTableEntryIdInt &&
7057 !wanted_type->data.integral.is_signed)
7058 {
7059 ir_add_error(ira, source_instr,
7060 buf_sprintf("attempt to cast negative value to unsigned integer"));
7061 return ira->codegen->invalid_instruction;
7056 if (wanted_type->id == TypeTableEntryIdInt) {
7057 if (val->data.x_bignum.is_negative && !wanted_type->data.integral.is_signed) {
7058 ir_add_error(ira, source_instr,
7059 buf_sprintf("attempt to cast negative value to unsigned integer"));
7060 return ira->codegen->invalid_instruction;
7061 }
7062 if (!bignum_fits_in_bits(&val->data.x_bignum, wanted_type->data.integral.bit_count,
7063 wanted_type->data.integral.is_signed))
7064 {
7065 ir_add_error(ira, source_instr,
7066 buf_sprintf("cast from '%s' to '%s' truncates bits",
7067 buf_ptr(&target->value.type->name), buf_ptr(&wanted_type->name)));
7068 return ira->codegen->invalid_instruction;
7069 }
70627070 }
70637071 IrInstruction *result = ir_create_const(&ira->new_irb, source_instr->scope,
70647072 source_instr->source_node, wanted_type);
test/cases/eval.zig+8
......@@ -314,3 +314,11 @@ const global_array = {
314314 }
315315 result
316316};
317
318test "compile-time downcast when the bits fit" {
319 comptime {
320 const spartan_count: u16 = 255;
321 const byte = u8(spartan_count);
322 assert(byte == 255);
323 }
324}
test/compile_errors.zig+8
......@@ -1827,4 +1827,12 @@ pub fn addCases(cases: &tests.CompileErrorContext) {
18271827 \\}
18281828 ,
18291829 ".tmp_source.zig:4:17: error: division by zero is undefined");
1830
1831 cases.add("compile-time integer cast truncates bits",
1832 \\comptime {
1833 \\ const spartan_count: u16 = 300;
1834 \\ const byte = u8(spartan_count);
1835 \\}
1836 ,
1837 ".tmp_source.zig:3:20: error: cast from 'u16' to 'u8' truncates bits");
18301838}