authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-07 19:11:26+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-08 00:37:11+03:00
log0fa80e66b7e995e560ac1c3da7069c603e9a0538
treed7fbef95a5d041a1deeca0c73ce9a572b06d4edc
parent924679abc46deeaae9284ab6ce928aaddb0fae95

Sema: correct types in `@memset` and `@memcpy`

Closes #12750

2 files changed, 40 insertions(+), 29 deletions(-)

src/Sema.zig+21-29
......@@ -18076,8 +18076,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6
1807618076 const target = sema.mod.getTarget();
1807718077
1807818078 try sema.resolveTypeLayout(block, lhs_src, ty);
18079 switch (ty.tag()) {
18080 .@"struct", .tuple, .anon_struct => {},
18079 switch (ty.zigTypeTag()) {
18080 .Struct => {},
1808118081 else => {
1808218082 const msg = msg: {
1808318083 const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)});
......@@ -19617,28 +19617,19 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
1961719617 const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1961819618 const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1961919619 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
19620 const dest_ptr = try sema.resolveInst(extra.dest);
19621 const dest_ptr_ty = sema.typeOf(dest_ptr);
19620 const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
1962219621
19623 try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
19624 if (dest_ptr_ty.isConstPtr()) {
19625 return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
19626 }
19622 // TODO AstGen's coerced_ty cannot handle volatile here
19623 var dest_ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
19624 dest_ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
19625 const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, dest_ptr_info);
19626 const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
1962719627
1962819628 const uncasted_src_ptr = try sema.resolveInst(extra.source);
19629 const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr);
19630 try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty);
19631 const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data;
19632 const wanted_src_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{
19633 .pointee_type = dest_ptr_ty.elemType2(),
19634 .@"align" = src_ptr_info.@"align",
19635 .@"addrspace" = src_ptr_info.@"addrspace",
19636 .mutable = false,
19637 .@"allowzero" = src_ptr_info.@"allowzero",
19638 .@"volatile" = src_ptr_info.@"volatile",
19639 .size = .Many,
19640 });
19641 const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src);
19629 var src_ptr_info = Type.initTag(.manyptr_const_u8).ptrInfo().data;
19630 src_ptr_info.@"volatile" = sema.typeOf(uncasted_src_ptr).isVolatilePtr();
19631 const src_ptr_ty = try Type.ptr(sema.arena, sema.mod, src_ptr_info);
19632 const src_ptr = try sema.coerce(block, src_ptr_ty, uncasted_src_ptr, src_src);
1964219633 const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
1964319634
1964419635 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: {
......@@ -19674,14 +19665,15 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
1967419665 const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
1967519666 const value_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
1967619667 const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node };
19677 const dest_ptr = try sema.resolveInst(extra.dest);
19678 const dest_ptr_ty = sema.typeOf(dest_ptr);
19679 try sema.checkPtrOperand(block, dest_src, dest_ptr_ty);
19680 if (dest_ptr_ty.isConstPtr()) {
19681 return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)});
19682 }
19683 const elem_ty = dest_ptr_ty.elemType2();
19684 const value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.byte), value_src);
19668 const uncasted_dest_ptr = try sema.resolveInst(extra.dest);
19669
19670 // TODO AstGen's coerced_ty cannot handle volatile here
19671 var ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data;
19672 ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr();
19673 const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
19674 const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src);
19675
19676 const value = try sema.coerce(block, Type.u8, try sema.resolveInst(extra.byte), value_src);
1968519677 const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src);
1968619678
1968719679 const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: {
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig created+19
......@@ -0,0 +1,19 @@
1pub export fn entry() void {
2 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
3 var slice: []u8 = &buf;
4 const a: u32 = 1234;
5 @memcpy(slice, @ptrCast([*]const u8, &a), 4);
6}
7pub export fn entry1() void {
8 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
9 var ptr: *u8 = &buf[0];
10 @memcpy(ptr, 0, 4);
11}
12
13// error
14// backend=stage2
15// target=native
16//
17// :5:13: error: expected type '[*]u8', found '[]u8'
18// :10:13: error: expected type '[*]u8', found '*u8'
19// :10:13: note: a single pointer cannot cast into a many pointer