authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-24 17:31:07-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-25 11:23:41-07:00
log1ba72bcf9a86060fc39117f89536a971ace620c4
tree0c4b819a94bdc1692a17d4a0e542505d1f9c0b6e
parent747f58366a25593431a0e8ff85d76095e0e39e74

update test cases for new memcpy/memset semantics


11 files changed, 137 insertions(+), 28 deletions(-)

lib/std/zig/c_builtins.zig+4-4
...@@ -171,10 +171,10 @@ pub inline fn __builtin_memcpy(...@@ -171,10 +171,10 @@ pub inline fn __builtin_memcpy(
171 noalias src: ?*const anyopaque,171 noalias src: ?*const anyopaque,
172 len: usize,172 len: usize,
173) ?*anyopaque {173) ?*anyopaque {
174 const dst_cast = @ptrCast([*c]u8, dst);174 if (len > 0) @memcpy(
175 const src_cast = @ptrCast([*c]const u8, src);175 @ptrCast([*]u8, dst.?)[0..len],
176176 @ptrCast([*]const u8, src.?),
177 @memcpy(dst_cast[0..len], src_cast);177 );
178 return dst;178 return dst;
179}179}
180180
src/Sema.zig+1-17
...@@ -20424,22 +20424,6 @@ fn checkPtrType(...@@ -20424,22 +20424,6 @@ fn checkPtrType(
20424 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});20424 return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});
20425}20425}
2042620426
20427fn checkSliceOrArrayType(
20428 sema: *Sema,
20429 block: *Block,
20430 ty_src: LazySrcLoc,
20431 ty: Type,
20432) CompileError!void {
20433 if (ty.zigTypeTag() == .Pointer) {
20434 switch (ty.ptrSize()) {
20435 .Slice => return,
20436 .One => if (ty.childType().zigTypeTag() == .Array) return,
20437 else => {},
20438 }
20439 }
20440 return sema.fail(block, ty_src, "expected slice or array pointer; found '{}'", .{ty.fmt(sema.mod)});
20441}
20442
20443fn checkVectorElemType(20427fn checkVectorElemType(
20444 sema: *Sema,20428 sema: *Sema,
20445 block: *Block,20429 block: *Block,
...@@ -21993,7 +21977,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void...@@ -21993,7 +21977,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
21993 const dest_ptr = try sema.resolveInst(extra.lhs);21977 const dest_ptr = try sema.resolveInst(extra.lhs);
21994 const uncoerced_elem = try sema.resolveInst(extra.rhs);21978 const uncoerced_elem = try sema.resolveInst(extra.rhs);
21995 const dest_ptr_ty = sema.typeOf(dest_ptr);21979 const dest_ptr_ty = sema.typeOf(dest_ptr);
21996 try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty);21980 try checkIndexable(sema, block, dest_src, dest_ptr_ty);
2199721981
21998 const dest_elem_ty = dest_ptr_ty.elemType2();21982 const dest_elem_ty = dest_ptr_ty.elemType2();
21999 const target = sema.mod.getTarget();21983 const target = sema.mod.getTarget();
test/behavior/builtin_functions_returning_void_or_noreturn.zig+2-2
...@@ -17,8 +17,8 @@ test {...@@ -17,8 +17,8 @@ test {
17 try testing.expectEqual(void, @TypeOf(@breakpoint()));17 try testing.expectEqual(void, @TypeOf(@breakpoint()));
18 try testing.expectEqual({}, @export(x, .{ .name = "x" }));18 try testing.expectEqual({}, @export(x, .{ .name = "x" }));
19 try testing.expectEqual({}, @fence(.Acquire));19 try testing.expectEqual({}, @fence(.Acquire));
20 try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1), @intToPtr([*]u8, 1), 0));20 try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1)[0..0], @intToPtr([*]u8, 1)[0..0]));
21 try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1), undefined, 0));21 try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1)[0..0], undefined));
22 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));22 try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
23 try testing.expectEqual({}, @prefetch(&val, .{}));23 try testing.expectEqual({}, @prefetch(&val, .{}));
24 try testing.expectEqual({}, @setAlignStack(16));24 try testing.expectEqual({}, @setAlignStack(16));
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig+21-4
...@@ -2,18 +2,35 @@ pub export fn entry() void {...@@ -2,18 +2,35 @@ pub export fn entry() void {
2 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };2 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
3 var slice: []u8 = &buf;3 var slice: []u8 = &buf;
4 const a: u32 = 1234;4 const a: u32 = 1234;
5 @memcpy(slice, @ptrCast([*]const u8, &a));5 @memcpy(slice.ptr, @ptrCast([*]const u8, &a));
6}6}
7pub export fn entry1() void {7pub export fn entry1() void {
8 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };8 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
9 var ptr: *u8 = &buf[0];9 var ptr: *u8 = &buf[0];
10 @memcpy(ptr, 0);10 @memcpy(ptr, 0);
11}11}
12pub export fn entry2() void {
13 var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
14 var ptr: *u8 = &buf[0];
15 @memset(ptr, 0);
16}
17pub export fn non_matching_lengths() void {
18 var buf1: [5]u8 = .{ 1, 2, 3, 4, 5 };
19 var buf2: [6]u8 = .{ 1, 2, 3, 4, 5, 6 };
20 @memcpy(&buf2, &buf1);
21}
1222
13// error23// error
14// backend=stage224// backend=stage2
15// target=native25// target=native
16//26//
17// :5:13: error: expected type '[*]u8', found '[]u8'27// :5:5: error: unknown @memcpy length
18// :10:13: error: expected type '[*]u8', found '*u8'28// :5:18: note: destination type [*]u8 provides no length
19// :10:13: note: a single pointer cannot cast into a many pointer29// :5:24: note: source type [*]align(4) const u8 provides no length
30// :10:13: error: type 'u8' does not support indexing
31// :10:13: note: for loop operand must be an array, slice, tuple, or vector
32// :15:13: error: type '*u8' does not support indexing
33// :15:13: note: for loop operand must be an array, slice, tuple, or vector
34// :20:5: error: non-matching @memcpy lengths
35// :20:13: note: length 6 here
36// :20:20: note: length 5 here
test/cases/safety/memcpy_alias.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "@memcpy arguments alias")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [2]u8{ 1, 2 } ** 5;
12 var len: usize = 5;
13 @memcpy(buffer[0..len], buffer[4 .. 4 + len]);
14}
15// run
16// backend=llvm
17// target=native
test/cases/safety/memcpy_len_mismatch.zig created+17
...@@ -0,0 +1,17 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "@memcpy arguments have non-equal lengths")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [2]u8{ 1, 2 } ** 5;
12 var len: usize = 5;
13 @memcpy(buffer[0..len], buffer[len .. len + 4]);
14}
15// run
16// backend=llvm
17// target=native
test/cases/safety/memset_array_undefined_bytes.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
12 @memset(&buffer, undefined);
13 var x: u8 = buffer[1];
14 x += buffer[2];
15}
16// run
17// backend=llvm
18// target=native
test/cases/safety/memset_array_undefined_large.zig created+18
...@@ -0,0 +1,18 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
12 @memset(&buffer, undefined);
13 var x: i32 = buffer[1];
14 x += buffer[2];
15}
16// run
17// backend=llvm
18// target=native
test/cases/safety/memset_slice_undefined_bytes.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
12 var len = buffer.len;
13 @memset(buffer[0..len], undefined);
14 var x: u8 = buffer[1];
15 x += buffer[2];
16}
17// run
18// backend=llvm
19// target=native
test/cases/safety/memset_slice_undefined_large.zig created+19
...@@ -0,0 +1,19 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer overflow")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10pub fn main() !void {
11 var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
12 var len = buffer.len;
13 @memset(buffer[0..len], undefined);
14 var x: i32 = buffer[1];
15 x += buffer[2];
16}
17// run
18// backend=llvm
19// target=native
test/cases/safety/switch on corrupted union value.zig +1-1
...@@ -15,7 +15,7 @@ const U = union(enum(u32)) {...@@ -15,7 +15,7 @@ const U = union(enum(u32)) {
1515
16pub fn main() !void {16pub fn main() !void {
17 var u: U = undefined;17 var u: U = undefined;
18 @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));18 @memset(@ptrCast([*]u8, &u)[0..@sizeOf(U)], 0x55);
19 switch (u) {19 switch (u) {
20 .X, .Y => @breakpoint(),20 .X, .Y => @breakpoint(),
21 }21 }