Commit 1ba72bcf9a
Changed files (11)
lib
std
src
test
lib/std/zig/c_builtins.zig
@@ -171,10 +171,10 @@ pub inline fn __builtin_memcpy(
noalias src: ?*const anyopaque,
len: usize,
) ?*anyopaque {
- const dst_cast = @ptrCast([*c]u8, dst);
- const src_cast = @ptrCast([*c]const u8, src);
-
- @memcpy(dst_cast[0..len], src_cast);
+ if (len > 0) @memcpy(
+ @ptrCast([*]u8, dst.?)[0..len],
+ @ptrCast([*]const u8, src.?),
+ );
return dst;
}
src/Sema.zig
@@ -20424,22 +20424,6 @@ fn checkPtrType(
return sema.fail(block, ty_src, "expected pointer type, found '{}'", .{ty.fmt(sema.mod)});
}
-fn checkSliceOrArrayType(
- sema: *Sema,
- block: *Block,
- ty_src: LazySrcLoc,
- ty: Type,
-) CompileError!void {
- if (ty.zigTypeTag() == .Pointer) {
- switch (ty.ptrSize()) {
- .Slice => return,
- .One => if (ty.childType().zigTypeTag() == .Array) return,
- else => {},
- }
- }
- return sema.fail(block, ty_src, "expected slice or array pointer; found '{}'", .{ty.fmt(sema.mod)});
-}
-
fn checkVectorElemType(
sema: *Sema,
block: *Block,
@@ -21993,7 +21977,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void
const dest_ptr = try sema.resolveInst(extra.lhs);
const uncoerced_elem = try sema.resolveInst(extra.rhs);
const dest_ptr_ty = sema.typeOf(dest_ptr);
- try checkSliceOrArrayType(sema, block, dest_src, dest_ptr_ty);
+ try checkIndexable(sema, block, dest_src, dest_ptr_ty);
const dest_elem_ty = dest_ptr_ty.elemType2();
const target = sema.mod.getTarget();
test/behavior/builtin_functions_returning_void_or_noreturn.zig
@@ -17,8 +17,8 @@ test {
try testing.expectEqual(void, @TypeOf(@breakpoint()));
try testing.expectEqual({}, @export(x, .{ .name = "x" }));
try testing.expectEqual({}, @fence(.Acquire));
- try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1), @intToPtr([*]u8, 1), 0));
- try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1), undefined, 0));
+ try testing.expectEqual({}, @memcpy(@intToPtr([*]u8, 1)[0..0], @intToPtr([*]u8, 1)[0..0]));
+ try testing.expectEqual({}, @memset(@intToPtr([*]u8, 1)[0..0], undefined));
try testing.expectEqual(noreturn, @TypeOf(if (true) @panic("") else {}));
try testing.expectEqual({}, @prefetch(&val, .{}));
try testing.expectEqual({}, @setAlignStack(16));
test/cases/compile_errors/incorrect_type_to_memset_memcpy.zig
@@ -2,18 +2,35 @@ 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));
+ @memcpy(slice.ptr, @ptrCast([*]const u8, &a));
}
pub export fn entry1() void {
var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
var ptr: *u8 = &buf[0];
@memcpy(ptr, 0);
}
+pub export fn entry2() void {
+ var buf: [5]u8 = .{ 1, 2, 3, 4, 5 };
+ var ptr: *u8 = &buf[0];
+ @memset(ptr, 0);
+}
+pub export fn non_matching_lengths() void {
+ var buf1: [5]u8 = .{ 1, 2, 3, 4, 5 };
+ var buf2: [6]u8 = .{ 1, 2, 3, 4, 5, 6 };
+ @memcpy(&buf2, &buf1);
+}
// 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
+// :5:5: error: unknown @memcpy length
+// :5:18: note: destination type [*]u8 provides no length
+// :5:24: note: source type [*]align(4) const u8 provides no length
+// :10:13: error: type 'u8' does not support indexing
+// :10:13: note: for loop operand must be an array, slice, tuple, or vector
+// :15:13: error: type '*u8' does not support indexing
+// :15:13: note: for loop operand must be an array, slice, tuple, or vector
+// :20:5: error: non-matching @memcpy lengths
+// :20:13: note: length 6 here
+// :20:20: note: length 5 here
test/cases/safety/memcpy_alias.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "@memcpy arguments alias")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [2]u8{ 1, 2 } ** 5;
+ var len: usize = 5;
+ @memcpy(buffer[0..len], buffer[4 .. 4 + len]);
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/memcpy_len_mismatch.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "@memcpy arguments have non-equal lengths")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [2]u8{ 1, 2 } ** 5;
+ var len: usize = 5;
+ @memcpy(buffer[0..len], buffer[len .. len + 4]);
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/memset_array_undefined_bytes.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer overflow")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
+ @memset(&buffer, undefined);
+ var x: u8 = buffer[1];
+ x += buffer[2];
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/memset_array_undefined_large.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer overflow")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
+ @memset(&buffer, undefined);
+ var x: i32 = buffer[1];
+ x += buffer[2];
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/memset_slice_undefined_bytes.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer overflow")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [6]u8{ 1, 2, 3, 4, 5, 6 };
+ var len = buffer.len;
+ @memset(buffer[0..len], undefined);
+ var x: u8 = buffer[1];
+ x += buffer[2];
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/memset_slice_undefined_large.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer overflow")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+pub fn main() !void {
+ var buffer = [6]i32{ 1, 2, 3, 4, 5, 6 };
+ var len = buffer.len;
+ @memset(buffer[0..len], undefined);
+ var x: i32 = buffer[1];
+ x += buffer[2];
+}
+// run
+// backend=llvm
+// target=native
test/cases/safety/switch on corrupted union value.zig
@@ -15,7 +15,7 @@ const U = union(enum(u32)) {
pub fn main() !void {
var u: U = undefined;
- @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
+ @memset(@ptrCast([*]u8, &u)[0..@sizeOf(U)], 0x55);
switch (u) {
.X, .Y => @breakpoint(),
}