From 0fa80e66b7e995e560ac1c3da7069c603e9a0538 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Wed, 7 Sep 2022 19:11:26 +0300 Subject: [PATCH] Sema: correct types in `@memset` and `@memcpy` Closes #12750 --- src/Sema.zig | 50 ++++++++----------- .../incorrect_type_to_memset_memcpy.zig | 19 +++++++ 2 files changed, 40 insertions(+), 29 deletions(-) create mode 100644 test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig diff --git a/src/Sema.zig b/src/Sema.zig index fb1638bc2a..417455ae5a 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -18076,8 +18076,8 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 const target = sema.mod.getTarget(); try sema.resolveTypeLayout(block, lhs_src, ty); - switch (ty.tag()) { - .@"struct", .tuple, .anon_struct => {}, + switch (ty.zigTypeTag()) { + .Struct => {}, else => { const msg = msg: { 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 const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const src_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; - const dest_ptr = try sema.resolveInst(extra.dest); - const dest_ptr_ty = sema.typeOf(dest_ptr); + const uncasted_dest_ptr = try sema.resolveInst(extra.dest); - try sema.checkPtrOperand(block, dest_src, dest_ptr_ty); - if (dest_ptr_ty.isConstPtr()) { - return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)}); - } + // TODO AstGen's coerced_ty cannot handle volatile here + var dest_ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data; + dest_ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr(); + const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, dest_ptr_info); + const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src); const uncasted_src_ptr = try sema.resolveInst(extra.source); - const uncasted_src_ptr_ty = sema.typeOf(uncasted_src_ptr); - try sema.checkPtrOperand(block, src_src, uncasted_src_ptr_ty); - const src_ptr_info = uncasted_src_ptr_ty.ptrInfo().data; - const wanted_src_ptr_ty = try Type.ptr(sema.arena, sema.mod, .{ - .pointee_type = dest_ptr_ty.elemType2(), - .@"align" = src_ptr_info.@"align", - .@"addrspace" = src_ptr_info.@"addrspace", - .mutable = false, - .@"allowzero" = src_ptr_info.@"allowzero", - .@"volatile" = src_ptr_info.@"volatile", - .size = .Many, - }); - const src_ptr = try sema.coerce(block, wanted_src_ptr_ty, uncasted_src_ptr, src_src); + var src_ptr_info = Type.initTag(.manyptr_const_u8).ptrInfo().data; + src_ptr_info.@"volatile" = sema.typeOf(uncasted_src_ptr).isVolatilePtr(); + const src_ptr_ty = try Type.ptr(sema.arena, sema.mod, src_ptr_info); + const src_ptr = try sema.coerce(block, src_ptr_ty, uncasted_src_ptr, src_src); const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src); 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 const dest_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; const value_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node }; const len_src: LazySrcLoc = .{ .node_offset_builtin_call_arg2 = inst_data.src_node }; - const dest_ptr = try sema.resolveInst(extra.dest); - const dest_ptr_ty = sema.typeOf(dest_ptr); - try sema.checkPtrOperand(block, dest_src, dest_ptr_ty); - if (dest_ptr_ty.isConstPtr()) { - return sema.fail(block, dest_src, "cannot store through const pointer '{}'", .{dest_ptr_ty.fmt(sema.mod)}); - } - const elem_ty = dest_ptr_ty.elemType2(); - const value = try sema.coerce(block, elem_ty, try sema.resolveInst(extra.byte), value_src); + const uncasted_dest_ptr = try sema.resolveInst(extra.dest); + + // TODO AstGen's coerced_ty cannot handle volatile here + var ptr_info = Type.initTag(.manyptr_u8).ptrInfo().data; + ptr_info.@"volatile" = sema.typeOf(uncasted_dest_ptr).isVolatilePtr(); + const dest_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); + const dest_ptr = try sema.coerce(block, dest_ptr_ty, uncasted_dest_ptr, dest_src); + + const value = try sema.coerce(block, Type.u8, try sema.resolveInst(extra.byte), value_src); const len = try sema.coerce(block, Type.usize, try sema.resolveInst(extra.byte_count), len_src); const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |ptr_val| rs: { diff --git a/test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig b/test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig new file mode 100644 index 0000000000..d3a6b7cc4b --- /dev/null +++ b/test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig @@ -0,0 +1,19 @@ +pub export fn entry() void { + var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; + var slice: []u8 = &buf; + const a: u32 = 1234; + @memcpy(slice, @ptrCast([*]const u8, &a), 4); +} +pub export fn entry1() void { + var buf: [5]u8 = .{ 1, 2, 3, 4, 5 }; + var ptr: *u8 = &buf[0]; + @memcpy(ptr, 0, 4); +} + +// error +// backend=stage2 +// target=native +// +// :5:13: error: expected type '[*]u8', found '[]u8' +// :10:13: error: expected type '[*]u8', found '*u8' +// :10:13: note: a single pointer cannot cast into a many pointer