zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit dcca5cf1a9241e7274ae03a587b7e3313d673f3e (tree)
parent 289eab9177443bdfadfe750afda8f7f32f43be0f
Author: Andrew Kelley <andrew@ziglang.org>
Date:   Sun,  5 Jul 2020 22:24:25 +0000

Merge pull request #5797 from xackus/intcast-runtime-safety

stage1: `@intcast` runtime safety for unsigned -> signed of same bit count
Diffstat:
Mlib/std/special/compiler_rt/clzsi2_test.zig | 2+-
Mlib/std/special/compiler_rt/int.zig | 2+-
Mlib/std/special/compiler_rt/udivmod.zig | 2+-
Msrc/codegen.cpp | 10++++++----
Mtest/runtime_safety.zig | 10++++++++++
5 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/lib/std/special/compiler_rt/clzsi2_test.zig b/lib/std/special/compiler_rt/clzsi2_test.zig @@ -4,7 +4,7 @@ const testing = @import("std").testing; fn test__clzsi2(a: u32, expected: i32) void { var nakedClzsi2 = clzsi2.__clzsi2; var actualClzsi2 = @ptrCast(fn (a: i32) callconv(.C) i32, nakedClzsi2); - var x = @intCast(i32, a); + var x = @bitCast(i32, a); var result = actualClzsi2(x); testing.expectEqual(expected, result); } diff --git a/lib/std/special/compiler_rt/int.zig b/lib/std/special/compiler_rt/int.zig @@ -244,7 +244,7 @@ pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 { // r.all -= d.all; // carry = 1; // } - const s = @intCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1); + const s = @bitCast(i32, d -% r -% 1) >> @intCast(u5, n_uword_bits - 1); carry = @intCast(u32, s & 1); r -= d & @bitCast(u32, s); } diff --git a/lib/std/special/compiler_rt/udivmod.zig b/lib/std/special/compiler_rt/udivmod.zig @@ -184,7 +184,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: // carry = 1; // } r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421 - const s: SignedDoubleInt = @intCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1); + const s: SignedDoubleInt = @bitCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1); carry = @intCast(u32, s & 1); r_all -= b & @bitCast(DoubleInt, s); r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421 diff --git a/src/codegen.cpp b/src/codegen.cpp @@ -1535,9 +1535,11 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z zig_unreachable(); } - if (actual_type->id == ZigTypeIdInt && - !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && - want_runtime_safety) + if (actual_type->id == ZigTypeIdInt && want_runtime_safety && ( + // negative to unsigned + (!wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed) || + // unsigned would become negative + (wanted_type->data.integral.is_signed && !actual_type->data.integral.is_signed && actual_bits == wanted_bits))) { LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type)); 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 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_safety_crash(g, PanicMsgIdCastNegativeToUnsigned); + gen_safety_crash(g, actual_type->data.integral.is_signed ? PanicMsgIdCastNegativeToUnsigned : PanicMsgIdCastTruncatedData); LLVMPositionBuilderAtEnd(g->builder, ok_block); } diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig @@ -757,6 +757,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { \\} ); + cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count", + \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { + \\ @import("std").os.exit(126); + \\} + \\pub fn main() void { + \\ var value: u8 = 245; + \\ var casted = @intCast(i8, value); + \\} + ); + cases.addRuntimeSafety("unwrap error", \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) {