Commit bfcfaaf5bd

Andrew Kelley <superjoe30@gmail.com>
2018-09-18 02:32:51
fix codegen for @intCast to u0
1 parent 15e59eb
Changed files (3)
src/codegen.cpp
@@ -1689,6 +1689,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
         if (actual_type->id == ZigTypeIdFloat) {
             return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
         } else if (actual_type->id == ZigTypeIdInt) {
+            if (wanted_bits == 0) {
+                if (!want_runtime_safety)
+                    return nullptr;
+
+                LLVMValueRef zero = LLVMConstNull(actual_type->type_ref);
+                LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, "");
+                LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk");
+                LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail");
+                LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+                LLVMPositionBuilderAtEnd(g->builder, fail_block);
+                gen_safety_crash(g, PanicMsgIdCastTruncatedData);
+
+                LLVMPositionBuilderAtEnd(g->builder, ok_block);
+                return nullptr;
+            }
             LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
             if (!want_runtime_safety) {
                 return trunc_val;
test/cases/eval.zig
@@ -692,4 +692,11 @@ test "zero extend from u0 to u1" {
 test "bit shift a u1" {
     var x: u1 = 1;
     var y = x << 0;
+    assert(y == 1);
+}
+
+test "@intCast to a u0" {
+    var x: u8 = 0;
+    var y: u0 = @intCast(u0, x);
+    assert(y == 0);
 }
test/runtime_safety.zig
@@ -249,6 +249,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
         \\}
     );
 
+    cases.addRuntimeSafety("value does not fit in shortening cast - u0",
+        \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
+        \\    @import("std").os.exit(126);
+        \\}
+        \\pub fn main() !void {
+        \\    const x = shorten_cast(1);
+        \\    if (x == 0) return error.Whatever;
+        \\}
+        \\fn shorten_cast(x: u8) u0 {
+        \\    return @intCast(u0, x);
+        \\}
+    );
+
     cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
         \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
         \\    @import("std").os.exit(126);