authorgravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-07-05 17:58:21+02:00
committergravatar for 14938807+xackus@users.noreply.github.comxackus <14938807+xackus@users.noreply.github.com> 2020-07-05 17:58:21+02:00
log51f8c306d9fa32c849b26c2d95a45901a02f448e
tree80a09b965eaa0ff2849f3eafc7405eb9af3146ff
parent0ae1157e4553d6f54e0d489daebb006c402e0f63

stage1: add missing runtime safety for @intCast unsigned -> signed of same bit count


2 files changed, 16 insertions(+), 4 deletions(-)

src/codegen.cpp+6-4
...@@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1535 zig_unreachable();1535 zig_unreachable();
1536 }1536 }
15371537
1538 if (actual_type->id == ZigTypeIdInt &&1538 if (actual_type->id == ZigTypeIdInt && want_runtime_safety && (
1539 !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed &&1539 // negative to unsigned
1540 want_runtime_safety)1540 (!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed) ||
1541 // unsigned would become negative
1542 (wanted_type->data.integral.is_signed && !actual_type->data.integral.is_signed && actual_bits == wanted_bits)))
1541 {1543 {
1542 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));1544 LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type));
1543 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");1545 LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, "");
...@@ -1547,7 +1549,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z...@@ -1547,7 +1549,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
1547 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);1549 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
15481550
1549 LLVMPositionBuilderAtEnd(g->builder, fail_block);1551 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1550 gen_safety_crash(g, PanicMsgIdCastNegativeToUnsigned);1552 gen_safety_crash(g, actual_type->data.integral.is_signed ? PanicMsgIdCastNegativeToUnsigned : PanicMsgIdCastTruncatedData);
15511553
1552 LLVMPositionBuilderAtEnd(g->builder, ok_block);1554 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1553 }1555 }
test/runtime_safety.zig+10
...@@ -757,6 +757,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -757,6 +757,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
757 \\}757 \\}
758 );758 );
759759
760 cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",
761 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
762 \\ @import("std").os.exit(126);
763 \\}
764 \\pub fn main() void {
765 \\ var value: u8 = 245;
766 \\ var casted = @intCast(i8, value);
767 \\}
768 );
769
760 cases.addRuntimeSafety("unwrap error",770 cases.addRuntimeSafety("unwrap error",
761 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {771 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
762 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {772 \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {