| author | |
| committer | |
| log | 8fbac2e86d35bf363b67aba0f1915b7c9d32dcd0 |
| tree | 76a8a0dc223a24db92c680fc70262ab80ca9b702 |
| parent | 01698528d1dff627b7e057651b137c20df7c7231 |
| signature |
5 files changed, 22 insertions(+), 3 deletions(-)
src/Sema.zig+18-3| ... | @@ -6781,14 +6781,27 @@ fn intCast( | ... | @@ -6781,14 +6781,27 @@ fn intCast( |
| 6781 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); | 6781 | return sema.fail(block, operand_src, "unable to cast runtime value to 'comptime_int'", .{}); |
| 6782 | } | 6782 | } |
| 6783 | 6783 | ||
| 6784 | // TODO insert safety check to make sure the value fits in the dest type | ||
| 6785 | _ = runtime_safety; | ||
| 6786 | |||
| 6787 | if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| { | 6784 | if ((try sema.typeHasOnePossibleValue(block, dest_ty_src, dest_ty))) |opv| { |
| 6788 | return sema.addConstant(dest_ty, opv); | 6785 | return sema.addConstant(dest_ty, opv); |
| 6789 | } | 6786 | } |
| 6790 | 6787 | ||
| 6791 | try sema.requireRuntimeBlock(block, operand_src); | 6788 | try sema.requireRuntimeBlock(block, operand_src); |
| 6789 | if (runtime_safety) { | ||
| 6790 | const target = sema.mod.getTarget(); | ||
| 6791 | const operand_ty = sema.typeOf(operand); | ||
| 6792 | const actual_info = operand_ty.intInfo(target); | ||
| 6793 | const wanted_info = dest_ty.intInfo(target); | ||
| 6794 | const actual_bits = actual_info.bits; | ||
| 6795 | const wanted_bits = wanted_info.bits; | ||
| 6796 | |||
| 6797 | // requirement: operand can fit into bit size of destination type | ||
| 6798 | if (actual_bits > wanted_bits) { | ||
| 6799 | const max_int = try dest_ty.maxInt(sema.arena, target); | ||
| 6800 | const max_int_inst = try sema.addConstant(operand_ty, max_int); | ||
| 6801 | const is_in_range = try block.addBinOp(.cmp_lte, operand, max_int_inst); | ||
| 6802 | try sema.addSafetyCheck(block, is_in_range, .cast_truncated_data); | ||
| 6803 | } | ||
| 6804 | } | ||
| 6792 | return block.addTyOp(.intcast, dest_ty, operand); | 6805 | return block.addTyOp(.intcast, dest_ty, operand); |
| 6793 | } | 6806 | } |
| 6794 | 6807 | ||
| ... | @@ -16166,6 +16179,7 @@ pub const PanicId = enum { | ... | @@ -16166,6 +16179,7 @@ pub const PanicId = enum { |
| 16166 | incorrect_alignment, | 16179 | incorrect_alignment, |
| 16167 | invalid_error_code, | 16180 | invalid_error_code, |
| 16168 | index_out_of_bounds, | 16181 | index_out_of_bounds, |
| 16182 | cast_truncated_data, | ||
| 16169 | }; | 16183 | }; |
| 16170 | 16184 | ||
| 16171 | fn addSafetyCheck( | 16185 | fn addSafetyCheck( |
| ... | @@ -16288,6 +16302,7 @@ fn safetyPanic( | ... | @@ -16288,6 +16302,7 @@ fn safetyPanic( |
| 16288 | .incorrect_alignment => "incorrect alignment", | 16302 | .incorrect_alignment => "incorrect alignment", |
| 16289 | .invalid_error_code => "invalid error code", | 16303 | .invalid_error_code => "invalid error code", |
| 16290 | .index_out_of_bounds => "attempt to index out of bounds", | 16304 | .index_out_of_bounds => "attempt to index out of bounds", |
| 16305 | .cast_truncated_data => "integer cast truncated bits", | ||
| 16291 | }; | 16306 | }; |
| 16292 | 16307 | ||
| 16293 | const msg_inst = msg_inst: { | 16308 | const msg_inst = msg_inst: { |
test/behavior/eval.zig+1| ... | @@ -443,6 +443,7 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { | ... | @@ -443,6 +443,7 @@ fn copyWithPartialInline(s: []u32, b: []u8) void { |
| 443 | test "binary math operator in partially inlined function" { | 443 | test "binary math operator in partially inlined function" { |
| 444 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 444 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 445 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 445 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 446 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 446 | 447 | ||
| 447 | var s: [4]u32 = undefined; | 448 | var s: [4]u32 = undefined; |
| 448 | var b: [16]u8 = undefined; | 449 | var b: [16]u8 = undefined; |
test/behavior/fn.zig+1| ... | @@ -315,6 +315,7 @@ test "function pointers" { | ... | @@ -315,6 +315,7 @@ test "function pointers" { |
| 315 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 315 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 316 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 316 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 317 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 317 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 318 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 318 | 319 | ||
| 319 | const fns = [_]*const @TypeOf(fn1){ | 320 | const fns = [_]*const @TypeOf(fn1){ |
| 320 | &fn1, | 321 | &fn1, |
test/behavior/for.zig+1| ... | @@ -69,6 +69,7 @@ test "basic for loop" { | ... | @@ -69,6 +69,7 @@ test "basic for loop" { |
| 69 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | 69 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; |
| 70 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 70 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 71 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 71 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 72 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | ||
| 72 | 73 | ||
| 73 | const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; | 74 | const expected_result = [_]u8{ 9, 8, 7, 6, 0, 1, 2, 3 } ** 3; |
| 74 | 75 |
test/behavior/int128.zig+1| ... | @@ -46,6 +46,7 @@ test "int128" { | ... | @@ -46,6 +46,7 @@ test "int128" { |
| 46 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | 46 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO |
| 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 48 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 48 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 49 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | ||
| 49 | 50 | ||
| 50 | var buff: i128 = -1; | 51 | var buff: i128 = -1; |
| 51 | try expect(buff < 0 and (buff + 1) == 0); | 52 | try expect(buff < 0 and (buff + 1) == 0); |