| author | |
| committer | |
| log | bfcfaaf5bd5d2586d815ca5c10009975acf3e514 |
| tree | c2a3580527c2fae812a9fc2c2af37679d7e4a33f |
| parent | 15e59eb142af9d4385b9ce5a277df27804e1794e |
| signature |
3 files changed, 36 insertions(+), 0 deletions(-)
src/codegen.cpp+16| ... | ... | @@ -1689,6 +1689,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1689 | 1689 | if (actual_type->id == ZigTypeIdFloat) { |
| 1690 | 1690 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1691 | 1691 | } else if (actual_type->id == ZigTypeIdInt) { |
| 1692 | if (wanted_bits == 0) { | |
| 1693 | if (!want_runtime_safety) | |
| 1694 | return nullptr; | |
| 1695 | ||
| 1696 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); | |
| 1697 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, ""); | |
| 1698 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); | |
| 1699 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail"); | |
| 1700 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | |
| 1701 | ||
| 1702 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | |
| 1703 | gen_safety_crash(g, PanicMsgIdCastTruncatedData); | |
| 1704 | ||
| 1705 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | |
| 1706 | return nullptr; | |
| 1707 | } | |
| 1692 | 1708 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1693 | 1709 | if (!want_runtime_safety) { |
| 1694 | 1710 | return trunc_val; |
test/cases/eval.zig+7| ... | ... | @@ -692,4 +692,11 @@ test "zero extend from u0 to u1" { |
| 692 | 692 | test "bit shift a u1" { |
| 693 | 693 | var x: u1 = 1; |
| 694 | 694 | var y = x << 0; |
| 695 | assert(y == 1); | |
| 696 | } | |
| 697 | ||
| 698 | test "@intCast to a u0" { | |
| 699 | var x: u8 = 0; | |
| 700 | var y: u0 = @intCast(u0, x); | |
| 701 | assert(y == 0); | |
| 695 | 702 | } |
test/runtime_safety.zig+13| ... | ... | @@ -249,6 +249,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 249 | 249 | \\} |
| 250 | 250 | ); |
| 251 | 251 | |
| 252 | cases.addRuntimeSafety("value does not fit in shortening cast - u0", | |
| 253 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 254 | \\ @import("std").os.exit(126); | |
| 255 | \\} | |
| 256 | \\pub fn main() !void { | |
| 257 | \\ const x = shorten_cast(1); | |
| 258 | \\ if (x == 0) return error.Whatever; | |
| 259 | \\} | |
| 260 | \\fn shorten_cast(x: u8) u0 { | |
| 261 | \\ return @intCast(u0, x); | |
| 262 | \\} | |
| 263 | ); | |
| 264 | ||
| 252 | 265 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", |
| 253 | 266 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 254 | 267 | \\ @import("std").os.exit(126); |