Merge pull request #5797 from xackus/intcast-runtime-safety
stage1: `@intcast` runtime safety for unsigned -> signed of same bit count
This commit is contained in:
commit
dcca5cf1a9
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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")) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user