| 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,6 +1689,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1689 | if (actual_type->id == ZigTypeIdFloat) { | 1689 | if (actual_type->id == ZigTypeIdFloat) { |
| 1690 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | 1690 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1691 | } else if (actual_type->id == ZigTypeIdInt) { | 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 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); | 1708 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1693 | if (!want_runtime_safety) { | 1709 | if (!want_runtime_safety) { |
| 1694 | return trunc_val; | 1710 | return trunc_val; |
test/cases/eval.zig+7| ... | @@ -692,4 +692,11 @@ test "zero extend from u0 to u1" { | ... | @@ -692,4 +692,11 @@ test "zero extend from u0 to u1" { |
| 692 | test "bit shift a u1" { | 692 | test "bit shift a u1" { |
| 693 | var x: u1 = 1; | 693 | var x: u1 = 1; |
| 694 | var y = x << 0; | 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,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 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", | 265 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", |
| 253 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | 266 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 254 | \\ @import("std").os.exit(126); | 267 | \\ @import("std").os.exit(126); |