aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-07-05 22:24:25 +0000
committerGitHub <noreply@github.com>2020-07-05 22:24:25 +0000
commitdcca5cf1a9241e7274ae03a587b7e3313d673f3e (patch)
tree6b4ca8bd860d267f3c75ba37e78d0acd9bc49753
parent289eab9177443bdfadfe750afda8f7f32f43be0f (diff)
parentb8553b4813e971e50dcae7b8181e5f6771f3dbff (diff)
downloadzig-dcca5cf1a9241e7274ae03a587b7e3313d673f3e.tar.gz
zig-dcca5cf1a9241e7274ae03a587b7e3313d673f3e.zip
Merge pull request #5797 from xackus/intcast-runtime-safety
stage1: `@intcast` runtime safety for unsigned -> signed of same bit count
-rw-r--r--lib/std/special/compiler_rt/clzsi2_test.zig2
-rw-r--r--lib/std/special/compiler_rt/int.zig2
-rw-r--r--lib/std/special/compiler_rt/udivmod.zig2
-rw-r--r--src/codegen.cpp10
-rw-r--r--test/runtime_safety.zig10
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
index ff94455846..8a2896fcb6 100644
--- 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
index eb731ee898..a72c13e233 100644
--- 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
index 7d519c34cb..ba53d1dee0 100644
--- 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
index 18ef7d9182..2f72861bc2 100644
--- 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
index e60d115a00..e27ae7e16e 100644
--- 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")) {