Commit 40cbf525f7

Andrew Kelley <andrew@ziglang.org>
2021-10-18 04:10:49
stage2: implement coercion from null to C pointer
1 parent e5dac0a
Changed files (4)
src/Sema.zig
@@ -4731,7 +4731,7 @@ fn zirFunc(
         body_inst,
         ret_ty_body,
         cc,
-        Value.initTag(.null_value),
+        Value.@"null",
         false,
         inferred_error_set,
         false,
@@ -8105,7 +8105,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             // return_type: ?type,
             field_values[4] = try Value.Tag.ty.create(sema.arena, ty.fnReturnType());
             // args: []const FnArg,
-            field_values[5] = Value.initTag(.null_value); // TODO
+            field_values[5] = Value.@"null"; // TODO
 
             return sema.addConstant(
                 type_info_ty,
@@ -8163,7 +8163,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             // is_allowzero: bool,
             field_values[5] = if (info.@"allowzero") Value.initTag(.bool_true) else Value.initTag(.bool_false);
             // sentinel: anytype,
-            field_values[6] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);
+            field_values[6] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.@"null";
 
             return sema.addConstant(
                 type_info_ty,
@@ -8181,7 +8181,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
             // child: type,
             field_values[1] = try Value.Tag.ty.create(sema.arena, info.elem_type);
             // sentinel: anytype,
-            field_values[2] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.initTag(.null_value);
+            field_values[2] = if (info.sentinel) |some| try Value.Tag.opt_payload.create(sema.arena, some) else Value.@"null";
 
             return sema.addConstant(
                 type_info_ty,
@@ -9753,7 +9753,7 @@ fn zirCmpxchg(
 
     // special case zero bit types
     if ((try sema.typeHasOnePossibleValue(block, elem_ty_src, elem_ty)) != null) {
-        return sema.addConstant(result_ty, Value.initTag(.null_value));
+        return sema.addConstant(result_ty, Value.@"null");
     }
 
     const runtime_src = if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| rs: {
@@ -9767,7 +9767,7 @@ fn zirCmpxchg(
                 const stored_val = (try ptr_val.pointerDeref(sema.arena)) orelse break :rs ptr_src;
                 const result_val = if (stored_val.eql(expected_val, elem_ty)) blk: {
                     try sema.storePtr(block, src, ptr, new_value);
-                    break :blk Value.initTag(.null_value);
+                    break :blk Value.@"null";
                 } else try Value.Tag.opt_payload.create(sema.arena, stored_val);
 
                 return sema.addConstant(result_ty, result_val);
@@ -10225,7 +10225,7 @@ fn zirVarExtended(
     //    extra_index += 1;
     //    const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
     //    break :blk align_tv.val;
-    //} else Value.initTag(.null_value);
+    //} else Value.@"null";
 
     const uncasted_init: Air.Inst.Ref = if (small.has_init) blk: {
         const init_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
@@ -10307,7 +10307,7 @@ fn zirFuncExtended(
         extra_index += 1;
         const align_tv = try sema.resolveInstConst(block, align_src, align_ref);
         break :blk align_tv.val;
-    } else Value.initTag(.null_value);
+    } else Value.@"null";
 
     const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
     extra_index += ret_ty_body.len;
@@ -10592,7 +10592,7 @@ fn panicWithMsg(
     });
     const null_stack_trace = try sema.addConstant(
         try Type.optional(arena, ptr_stack_trace_ty),
-        Value.initTag(.null_value),
+        Value.@"null",
     );
     const args = try arena.create([2]Air.Inst.Ref);
     args.* = .{ msg_inst, null_stack_trace };
@@ -11544,7 +11544,7 @@ fn coerce(
         .Optional => {
             // null to ?T
             if (inst_ty.zigTypeTag() == .Null) {
-                return sema.addConstant(dest_ty, Value.initTag(.null_value));
+                return sema.addConstant(dest_ty, Value.@"null");
             }
 
             // T to ?T
@@ -11605,6 +11605,13 @@ fn coerce(
                     .One => {},
                 }
             }
+
+            // coercion to C pointer
+            if (dest_ty.ptrSize() == .C) {
+                if (inst_ty.zigTypeTag() == .Null) {
+                    return sema.addConstant(dest_ty, Value.@"null");
+                }
+            }
         },
         .Int => {
             // integer widening
@@ -13806,7 +13813,7 @@ fn typeHasOnePossibleValue(
         .empty_struct, .empty_struct_literal => return Value.initTag(.empty_struct_value),
         .void => return Value.void,
         .noreturn => return Value.initTag(.unreachable_value),
-        .@"null" => return Value.initTag(.null_value),
+        .@"null" => return Value.@"null",
         .@"undefined" => return Value.initTag(.undef),
 
         .int_unsigned, .int_signed => {
src/value.zig
@@ -2824,6 +2824,7 @@ pub const Value = extern union {
     pub const negative_one: Value = .{ .ptr_otherwise = &negative_one_payload.base };
     pub const undef = initTag(.undef);
     pub const @"void" = initTag(.void_value);
+    pub const @"null" = initTag(.null_value);
 };
 
 var negative_one_payload: Value.Payload.I64 = .{
test/behavior/pointers.zig
@@ -44,3 +44,17 @@ test "double pointer parsing" {
 fn PtrOf(comptime T: type) type {
     return *T;
 }
+
+test "implicit cast single item pointer to C pointer and back" {
+    var y: u8 = 11;
+    var x: [*c]u8 = &y;
+    var z: *u8 = x;
+    z.* += 1;
+    try expect(y == 12);
+}
+
+test "initialize const optional C pointer to null" {
+    const a: ?[*c]i32 = null;
+    try expect(a == null);
+    comptime try expect(a == null);
+}
test/behavior/pointers_stage1.zig
@@ -29,14 +29,6 @@ test "assigning integer to C pointer" {
     }
 }
 
-test "implicit cast single item pointer to C pointer and back" {
-    var y: u8 = 11;
-    var x: [*c]u8 = &y;
-    var z: *u8 = x;
-    z.* += 1;
-    try expect(y == 12);
-}
-
 test "C pointer comparison and arithmetic" {
     const S = struct {
         fn doTheTest() !void {
@@ -103,12 +95,6 @@ test "implicit cast error unions with non-optional to optional pointer" {
     comptime try S.doTheTest();
 }
 
-test "initialize const optional C pointer to null" {
-    const a: ?[*c]i32 = null;
-    try expect(a == null);
-    comptime try expect(a == null);
-}
-
 test "compare equality of optional and non-optional pointer" {
     const a = @intToPtr(*const usize, 0x12345678);
     const b = @intToPtr(?*usize, 0x12345678);