Sema: implement coercion from pointers to *c_void

This commit is contained in:
Andrew Kelley 2021-10-25 11:34:23 -07:00
parent 8f3e1ea0f0
commit ed7328119f
3 changed files with 24 additions and 19 deletions

View File

@ -9711,10 +9711,7 @@ fn zirPtrCast(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
@tagName(dest_ty.zigTypeTag()), dest_ty,
});
}
if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
return sema.addConstant(dest_ty, val);
}
return block.addBitCast(dest_ty, operand);
return sema.coerceCompatiblePtrs(block, dest_ty, operand, operand_src);
}
fn zirTruncate(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@ -12096,6 +12093,14 @@ fn coerce(
else => {},
}
}
// cast from *T and [*]T to *c_void
// but don't do it if the source type is a double pointer
if (dest_info.pointee_type.tag() == .c_void and inst_ty.zigTypeTag() == .Pointer and
inst_ty.childType().zigTypeTag() != .Pointer)
{
return sema.coerceCompatiblePtrs(block, dest_ty, inst, inst_src);
}
},
.Int => {
// integer widening
@ -12808,7 +12813,7 @@ fn coerceCompatiblePtrs(
inst: Air.Inst.Ref,
inst_src: LazySrcLoc,
) !Air.Inst.Ref {
if (try sema.resolveDefinedValue(block, inst_src, inst)) |val| {
if (try sema.resolveMaybeUndefVal(block, inst_src, inst)) |val| {
// The comptime Value representation is compatible with both types.
return sema.addConstant(dest_ty, val);
}

View File

@ -106,3 +106,17 @@ test "comptime_int @intToFloat" {
try expect(result == 0x1_0000_0000_0000_0000.0);
}
}
test "implicit cast from [*]T to ?*c_void" {
var a = [_]u8{ 3, 2, 1 };
var runtime_zero: usize = 0;
incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
}
fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
var n: usize = 0;
while (n < len) : (n += 1) {
@ptrCast([*]u8, array.?)[n] += 1;
}
}

View File

@ -417,20 +417,6 @@ fn incrementVoidPtrValue(value: ?*c_void) void {
@ptrCast(*u8, value.?).* += 1;
}
test "implicit cast from [*]T to ?*c_void" {
var a = [_]u8{ 3, 2, 1 };
var runtime_zero: usize = 0;
incrementVoidPtrArray(a[runtime_zero..].ptr, 3);
try expect(std.mem.eql(u8, &a, &[_]u8{ 4, 3, 2 }));
}
fn incrementVoidPtrArray(array: ?*c_void, len: usize) void {
var n: usize = 0;
while (n < len) : (n += 1) {
@ptrCast([*]u8, array.?)[n] += 1;
}
}
test "*usize to *void" {
var i = @as(usize, 0);
var v = @ptrCast(*void, &i);