Commit 51f8c306d9

xackus <14938807+xackus@users.noreply.github.com>
2020-07-05 17:58:21
stage1: add missing runtime safety for @intCast unsigned -> signed of same bit count
1 parent 0ae1157
Changed files (2)
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);
     }
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")) {