authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-25 00:30:28-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-25 00:43:36-05:00
log29e438fd1f77a13c3a3f128434198ac024d3e195
tree73235c0b283adfdf0e621b7d0ed306f420d3d748
parent15d415e10b81a66fa3b887fb2a0c20bbcd614d94
signaturelock-open Commit is signed but in an unrecognized format.

more sentinel-terminated pointers std lib integration

See #3767

14 files changed, 98 insertions(+), 94 deletions(-)

doc/langref.html.in+1-1
......@@ -4865,7 +4865,7 @@ const mem = std.mem;
48654865test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
48664866 const window_name = [1][*]const u8{"window name"};
48674867 const x: [*]const ?[*]const u8 = &window_name;
4868 assert(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
4868 assert(mem.eql(u8, std.mem.toSliceConst(u8, @ptrCast([*:0]const u8, x[0].?)), "window name"));
48694869}
48704870 {#code_end#}
48714871 {#header_close#}
lib/std/c.zig+1-1
......@@ -102,7 +102,7 @@ pub extern "c" fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [
102102pub extern "c" fn dup(fd: fd_t) c_int;
103103pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;
104104pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;
105pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8;
105pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*:0]u8;
106106pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
107107pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
108108pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;
lib/std/debug.zig+8-8
......@@ -401,7 +401,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
401401 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
402402 const vaddr_end = vaddr_start + proc_sym.CodeSize;
403403 if (relative_address >= vaddr_start and relative_address < vaddr_end) {
404 break mem.toSliceConst(u8, @ptrCast([*]u8, proc_sym) + @sizeOf(pdb.ProcSym));
404 break mem.toSliceConst(u8, @ptrCast([*:0]u8, proc_sym) + @sizeOf(pdb.ProcSym));
405405 }
406406 },
407407 else => {},
......@@ -703,9 +703,9 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
703703 return;
704704 };
705705
706 const symbol_name = mem.toSliceConst(u8, di.strings.ptr + symbol.nlist.n_strx);
706 const symbol_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + symbol.nlist.n_strx));
707707 const compile_unit_name = if (symbol.ofile) |ofile| blk: {
708 const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
708 const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
709709 break :blk fs.path.basename(ofile_path);
710710 } else "???";
711711 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
......@@ -915,7 +915,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
915915 for (present) |_| {
916916 const name_offset = try pdb_stream.stream.readIntLittle(u32);
917917 const name_index = try pdb_stream.stream.readIntLittle(u32);
918 const name = mem.toSlice(u8, name_bytes.ptr + name_offset);
918 const name = mem.toSlice(u8, @ptrCast([*:0]u8, name_bytes.ptr + name_offset));
919919 if (mem.eql(u8, name, "/names")) {
920920 break :str_tab_index name_index;
921921 }
......@@ -1708,7 +1708,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17081708 const gop = try di.ofiles.getOrPut(ofile);
17091709 const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {
17101710 errdefer _ = di.ofiles.remove(ofile);
1711 const ofile_path = mem.toSliceConst(u8, di.strings.ptr + ofile.n_strx);
1711 const ofile_path = mem.toSliceConst(u8, @ptrCast([*:0]const u8, di.strings.ptr + ofile.n_strx));
17121712
17131713 gop.kv.value = MachOFile{
17141714 .bytes = try std.fs.Dir.cwd().readFileAllocAligned(
......@@ -1741,7 +1741,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
17411741 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
17421742 (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
17431743 {
1744 const sect_name = mem.toSliceConst(u8, &sect.sectname);
1744 const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &sect.sectname));
17451745 if (mem.eql(u8, sect_name, "__debug_line")) {
17461746 gop.kv.value.sect_debug_line = sect;
17471747 } else if (mem.eql(u8, sect_name, "__debug_info")) {
......@@ -2323,8 +2323,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
23232323 }
23242324}
23252325
2326fn readStringMem(ptr: *[*]const u8) []const u8 {
2327 const result = mem.toSliceConst(u8, ptr.*);
2326fn readStringMem(ptr: *[*]const u8) [:0]const u8 {
2327 const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*));
23282328 ptr.* += result.len + 1;
23292329 return result;
23302330}
lib/std/dynamic_library.zig+4-4
......@@ -140,7 +140,7 @@ pub const LinuxDynLib = struct {
140140};
141141
142142pub const ElfLib = struct {
143 strings: [*]u8,
143 strings: [*:0]u8,
144144 syms: [*]elf.Sym,
145145 hashtab: [*]os.Elf_Symndx,
146146 versym: ?[*]u16,
......@@ -175,7 +175,7 @@ pub const ElfLib = struct {
175175 const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
176176 if (base == maxInt(usize)) return error.BaseNotFound;
177177
178 var maybe_strings: ?[*]u8 = null;
178 var maybe_strings: ?[*:0]u8 = null;
179179 var maybe_syms: ?[*]elf.Sym = null;
180180 var maybe_hashtab: ?[*]os.Elf_Symndx = null;
181181 var maybe_versym: ?[*]u16 = null;
......@@ -186,7 +186,7 @@ pub const ElfLib = struct {
186186 while (dynv[i] != 0) : (i += 2) {
187187 const p = base + dynv[i + 1];
188188 switch (dynv[i]) {
189 elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),
189 elf.DT_STRTAB => maybe_strings = @intToPtr([*:0]u8, p),
190190 elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
191191 elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
192192 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
......@@ -230,7 +230,7 @@ pub const ElfLib = struct {
230230 }
231231};
232232
233fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool {
233fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*:0]u8) bool {
234234 var def = def_arg;
235235 const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
236236 while (true) {
lib/std/event/fs.zig+2-4
......@@ -58,8 +58,7 @@ pub const Request = struct {
5858 };
5959
6060 pub const Open = struct {
61 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
62 path: []const u8,
61 path: [:0]const u8,
6362 flags: u32,
6463 mode: File.Mode,
6564 result: Error!fd_t,
......@@ -68,8 +67,7 @@ pub const Request = struct {
6867 };
6968
7069 pub const WriteFile = struct {
71 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265
72 path: []const u8,
70 path: [:0]const u8,
7371 contents: []const u8,
7472 mode: File.Mode,
7573 result: Error!void,
lib/std/fs.zig+23-21
......@@ -28,6 +28,7 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
2828/// This represents the maximum size of a UTF-8 encoded file path.
2929/// All file system operations which return a path are guaranteed to
3030/// fit into a UTF-8 encoded array of this length.
31/// The byte count includes room for a null sentinel byte.
3132pub const MAX_PATH_BYTES = switch (builtin.os) {
3233 .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,
3334 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
......@@ -227,7 +228,7 @@ pub const AtomicFile = struct {
227228 try crypto.randomBytes(rand_buf[0..]);
228229 b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);
229230
230 const file = File.openWriteNoClobberC(&tmp_path_buf, mode) catch |err| switch (err) {
231 const file = File.openWriteNoClobberC(@ptrCast([*:0]u8, &tmp_path_buf), mode) catch |err| switch (err) {
231232 error.PathAlreadyExists => continue,
232233 // TODO zig should figure out that this error set does not include PathAlreadyExists since
233234 // it is handled in the above switch
......@@ -247,7 +248,7 @@ pub const AtomicFile = struct {
247248 pub fn deinit(self: *AtomicFile) void {
248249 if (!self.finished) {
249250 self.file.close();
250 deleteFileC(&self.tmp_path_buf) catch {};
251 deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
251252 self.finished = true;
252253 }
253254 }
......@@ -258,11 +259,11 @@ pub const AtomicFile = struct {
258259 self.finished = true;
259260 if (builtin.os == .windows) {
260261 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);
261 const tmp_path_w = try os.windows.cStrToPrefixedFileW(&self.tmp_path_buf);
262 const tmp_path_w = try os.windows.cStrToPrefixedFileW(@ptrCast([*:0]u8, &self.tmp_path_buf));
262263 return os.renameW(&tmp_path_w, &dest_path_w);
263264 }
264265 const dest_path_c = try os.toPosixPath(self.dest_path);
265 return os.renameC(&self.tmp_path_buf, &dest_path_c);
266 return os.renameC(@ptrCast([*:0]u8, &self.tmp_path_buf), &dest_path_c);
266267 }
267268};
268269
......@@ -274,12 +275,12 @@ pub fn makeDir(dir_path: []const u8) !void {
274275}
275276
276277/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.
277pub fn makeDirC(dir_path: [*]const u8) !void {
278pub fn makeDirC(dir_path: [*:0]const u8) !void {
278279 return os.mkdirC(dir_path, default_new_dir_mode);
279280}
280281
281282/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.
282pub fn makeDirW(dir_path: [*]const u16) !void {
283pub fn makeDirW(dir_path: [*:0]const u16) !void {
283284 return os.mkdirW(dir_path, default_new_dir_mode);
284285}
285286
......@@ -327,12 +328,12 @@ pub fn deleteDir(dir_path: []const u8) !void {
327328}
328329
329330/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.
330pub fn deleteDirC(dir_path: [*]const u8) !void {
331pub fn deleteDirC(dir_path: [*:0]const u8) !void {
331332 return os.rmdirC(dir_path);
332333}
333334
334335/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.
335pub fn deleteDirW(dir_path: [*]const u16) !void {
336pub fn deleteDirW(dir_path: [*:0]const u16) !void {
336337 return os.rmdirW(dir_path);
337338}
338339
......@@ -688,7 +689,7 @@ pub const Dir = struct {
688689 }
689690
690691 /// Same as `open` except the parameter is null-terminated.
691 pub fn openC(dir_path_c: [*]const u8) OpenError!Dir {
692 pub fn openC(dir_path_c: [*:0]const u8) OpenError!Dir {
692693 return cwd().openDirC(dir_path_c);
693694 }
694695
......@@ -708,7 +709,7 @@ pub const Dir = struct {
708709 }
709710
710711 /// Call `File.close` on the result when done.
711 pub fn openReadC(self: Dir, sub_path: [*]const u8) File.OpenError!File {
712 pub fn openReadC(self: Dir, sub_path: [*:0]const u8) File.OpenError!File {
712713 if (builtin.os == .windows) {
713714 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
714715 return self.openReadW(&path_w);
......@@ -719,7 +720,7 @@ pub const Dir = struct {
719720 return File.openHandle(fd);
720721 }
721722
722 pub fn openReadW(self: Dir, sub_path_w: [*]const u16) File.OpenError!File {
723 pub fn openReadW(self: Dir, sub_path_w: [*:0]const u16) File.OpenError!File {
723724 const w = os.windows;
724725
725726 var result = File{ .handle = undefined };
......@@ -786,7 +787,7 @@ pub const Dir = struct {
786787 }
787788
788789 /// Same as `openDir` except the parameter is null-terminated.
789 pub fn openDirC(self: Dir, sub_path_c: [*]const u8) OpenError!Dir {
790 pub fn openDirC(self: Dir, sub_path_c: [*:0]const u8) OpenError!Dir {
790791 if (builtin.os == .windows) {
791792 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
792793 return self.openDirW(&sub_path_w);
......@@ -805,7 +806,7 @@ pub const Dir = struct {
805806
806807 /// Same as `openDir` except the path parameter is UTF16LE, NT-prefixed.
807808 /// This function is Windows-only.
808 pub fn openDirW(self: Dir, sub_path_w: [*]const u16) OpenError!Dir {
809 pub fn openDirW(self: Dir, sub_path_w: [*:0]const u16) OpenError!Dir {
809810 const w = os.windows;
810811
811812 var result = Dir{
......@@ -868,7 +869,7 @@ pub const Dir = struct {
868869 }
869870
870871 /// Same as `deleteFile` except the parameter is null-terminated.
871 pub fn deleteFileC(self: Dir, sub_path_c: [*]const u8) DeleteFileError!void {
872 pub fn deleteFileC(self: Dir, sub_path_c: [*:0]const u8) DeleteFileError!void {
872873 os.unlinkatC(self.fd, sub_path_c, 0) catch |err| switch (err) {
873874 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
874875 else => |e| return e,
......@@ -903,7 +904,7 @@ pub const Dir = struct {
903904 }
904905
905906 /// Same as `deleteDir` except the parameter is null-terminated.
906 pub fn deleteDirC(self: Dir, sub_path_c: [*]const u8) DeleteDirError!void {
907 pub fn deleteDirC(self: Dir, sub_path_c: [*:0]const u8) DeleteDirError!void {
907908 os.unlinkatC(self.fd, sub_path_c, os.AT_REMOVEDIR) catch |err| switch (err) {
908909 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
909910 else => |e| return e,
......@@ -912,7 +913,7 @@ pub const Dir = struct {
912913
913914 /// Same as `deleteDir` except the parameter is UTF16LE, NT prefixed.
914915 /// This function is Windows-only.
915 pub fn deleteDirW(self: Dir, sub_path_w: [*]const u16) DeleteDirError!void {
916 pub fn deleteDirW(self: Dir, sub_path_w: [*:0]const u16) DeleteDirError!void {
916917 os.unlinkatW(self.fd, sub_path_w, os.AT_REMOVEDIR) catch |err| switch (err) {
917918 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
918919 else => |e| return e,
......@@ -927,7 +928,7 @@ pub const Dir = struct {
927928 }
928929
929930 /// Same as `readLink`, except the `pathname` parameter is null-terminated.
930 pub fn readLinkC(self: Dir, sub_path_c: [*]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
931 pub fn readLinkC(self: Dir, sub_path_c: [*:0]const u8, buffer: *[MAX_PATH_BYTES]u8) ![]u8 {
931932 return os.readlinkatC(self.fd, sub_path_c, buffer);
932933 }
933934
......@@ -1250,7 +1251,8 @@ pub fn openSelfExe() OpenSelfExeError!File {
12501251 var buf: [MAX_PATH_BYTES]u8 = undefined;
12511252 const self_exe_path = try selfExePath(&buf);
12521253 buf[self_exe_path.len] = 0;
1253 return File.openReadC(self_exe_path.ptr);
1254 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
1255 return File.openReadC(@ptrCast([*:0]u8, self_exe_path.ptr));
12541256}
12551257
12561258test "openSelfExe" {
......@@ -1277,7 +1279,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
12771279 var u32_len: u32 = out_buffer.len;
12781280 const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
12791281 if (rc != 0) return error.NameTooLong;
1280 return mem.toSlice(u8, out_buffer);
1282 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
12811283 }
12821284 switch (builtin.os) {
12831285 .linux => return os.readlinkC("/proc/self/exe", out_buffer),
......@@ -1306,9 +1308,9 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
13061308}
13071309
13081310/// The result is UTF16LE-encoded.
1309pub fn selfExePathW() []const u16 {
1311pub fn selfExePathW() [:0]const u16 {
13101312 const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;
1311 return mem.toSliceConst(u16, image_path_name.Buffer);
1313 return mem.toSliceConst(u16, @ptrCast([*:0]const u16, image_path_name.Buffer));
13121314}
13131315
13141316/// `selfExeDirPath` except allocates the result on the heap.
lib/std/fs/file.zig+7-7
......@@ -31,7 +31,7 @@ pub const File = struct {
3131 }
3232
3333 /// Deprecated; call `std.fs.Dir.openReadC` directly.
34 pub fn openReadC(path_c: [*]const u8) OpenError!File {
34 pub fn openReadC(path_c: [*:0]const u8) OpenError!File {
3535 return std.fs.Dir.cwd().openReadC(path_c);
3636 }
3737
......@@ -61,7 +61,7 @@ pub const File = struct {
6161
6262 /// Same as `openWriteMode` except `path` is null-terminated.
6363 /// TODO: deprecate this and move it to `std.fs.Dir`.
64 pub fn openWriteModeC(path: [*]const u8, file_mode: Mode) OpenError!File {
64 pub fn openWriteModeC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
6565 if (builtin.os == .windows) {
6666 const path_w = try windows.cStrToPrefixedFileW(path);
6767 return openWriteModeW(&path_w, file_mode);
......@@ -74,7 +74,7 @@ pub const File = struct {
7474
7575 /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded
7676 /// TODO: deprecate this and move it to `std.fs.Dir`.
77 pub fn openWriteModeW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
77 pub fn openWriteModeW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
7878 const handle = try windows.CreateFileW(
7979 path_w,
8080 windows.GENERIC_WRITE,
......@@ -101,7 +101,7 @@ pub const File = struct {
101101 }
102102
103103 /// TODO: deprecate this and move it to `std.fs.Dir`.
104 pub fn openWriteNoClobberC(path: [*]const u8, file_mode: Mode) OpenError!File {
104 pub fn openWriteNoClobberC(path: [*:0]const u8, file_mode: Mode) OpenError!File {
105105 if (builtin.os == .windows) {
106106 const path_w = try windows.cStrToPrefixedFileW(path);
107107 return openWriteNoClobberW(&path_w, file_mode);
......@@ -113,7 +113,7 @@ pub const File = struct {
113113 }
114114
115115 /// TODO: deprecate this and move it to `std.fs.Dir`.
116 pub fn openWriteNoClobberW(path_w: [*]const u16, file_mode: Mode) OpenError!File {
116 pub fn openWriteNoClobberW(path_w: [*:0]const u16, file_mode: Mode) OpenError!File {
117117 const handle = try windows.CreateFileW(
118118 path_w,
119119 windows.GENERIC_WRITE,
......@@ -142,13 +142,13 @@ pub const File = struct {
142142
143143 /// Same as `access` except the parameter is null-terminated.
144144 /// TODO: deprecate this and move it to `std.fs.Dir`.
145 pub fn accessC(path: [*]const u8) !void {
145 pub fn accessC(path: [*:0]const u8) !void {
146146 return os.accessC(path, os.F_OK);
147147 }
148148
149149 /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
150150 /// TODO: deprecate this and move it to `std.fs.Dir`.
151 pub fn accessW(path: [*]const u16) !void {
151 pub fn accessW(path: [*:0]const u16) !void {
152152 return os.accessW(path, os.F_OK);
153153 }
154154
lib/std/os.zig+37-33
......@@ -655,8 +655,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
655655
656656/// Open and possibly create a file. Keeps trying if it gets interrupted.
657657/// See also `open`.
658/// TODO https://github.com/ziglang/zig/issues/265
659pub fn openC(file_path: [*]const u8, flags: u32, perm: usize) OpenError!fd_t {
658pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
660659 while (true) {
661660 const rc = system.open(file_path, flags, perm);
662661 switch (errno(rc)) {
......@@ -697,7 +696,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: usize) Open
697696/// Open and possibly create a file. Keeps trying if it gets interrupted.
698697/// `file_path` is relative to the open directory handle `dir_fd`.
699698/// See also `openat`.
700pub fn openatC(dir_fd: fd_t, file_path: [*]const u8, flags: u32, mode: usize) OpenError!fd_t {
699pub fn openatC(dir_fd: fd_t, file_path: [*:0]const u8, flags: u32, mode: usize) OpenError!fd_t {
701700 while (true) {
702701 const rc = system.openat(dir_fd, file_path, flags, mode);
703702 switch (errno(rc)) {
......@@ -757,7 +756,7 @@ pub const ExecveError = error{
757756/// Like `execve` except the parameters are null-terminated,
758757/// matching the syscall API on all targets. This removes the need for an allocator.
759758/// This function ignores PATH environment variable. See `execvpeC` for that.
760pub fn execveC(path: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) ExecveError {
759pub fn execveC(path: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError {
761760 switch (errno(system.execve(path, child_argv, envp))) {
762761 0 => unreachable,
763762 EFAULT => unreachable,
......@@ -784,7 +783,7 @@ pub fn execveC(path: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]co
784783/// matching the syscall API on all targets. This removes the need for an allocator.
785784/// This function also uses the PATH environment variable to get the full path to the executable.
786785/// If `file` is an absolute path, this is the same as `execveC`.
787pub fn execvpeC(file: [*:0]const u8, child_argv: [*]const ?[*:0]const u8, envp: [*]const ?[*:0]const u8) ExecveError {
786pub fn execvpeC(file: [*:0]const u8, child_argv: [*:null]const ?[*:0]const u8, envp: [*:null]const ?[*:0]const u8) ExecveError {
788787 const file_slice = mem.toSliceConst(u8, file);
789788 if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp);
790789
......@@ -799,7 +798,8 @@ pub fn execvpeC(file: [*:0]const u8, child_argv: [*]const ?[*:0]const u8, envp:
799798 path_buf[search_path.len] = '/';
800799 mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice);
801800 path_buf[search_path.len + file_slice.len + 1] = 0;
802 err = execveC(&path_buf, child_argv, envp);
801 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
802 err = execveC(@ptrCast([*:0]u8, &path_buf), child_argv, envp);
803803 switch (err) {
804804 error.AccessDenied => seen_eacces = true,
805805 error.FileNotFound, error.NotDir => {},
......@@ -842,10 +842,13 @@ pub fn execvpe(
842842 const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);
843843 defer freeNullDelimitedEnvMap(allocator, envp_buf);
844844
845 return execvpeC(argv_buf.ptr[0].?, argv_buf.ptr, envp_buf.ptr);
845 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
846 const argv_ptr = @ptrCast([*:null]?[*:0]u8, argv_buf.ptr);
847
848 return execvpeC(argv_buf.ptr[0].?, argv_ptr, envp_buf.ptr);
846849}
847850
848pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![]?[*:0]u8 {
851pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![:null]?[*:0]u8 {
849852 const envp_count = env_map.count();
850853 const envp_buf = try allocator.alloc(?[*:0]u8, envp_count + 1);
851854 mem.set(?[*:0]u8, envp_buf, null);
......@@ -860,13 +863,14 @@ pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.
860863 @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);
861864 env_buf[env_buf.len - 1] = 0;
862865
863 // TODO avoid @ptrCast using slice syntax with https://github.com/ziglang/zig/issues/3731
866 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
864867 envp_buf[i] = @ptrCast([*:0]u8, env_buf.ptr);
865868 }
866869 assert(i == envp_count);
867870 }
871 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
868872 assert(envp_buf[envp_count] == null);
869 return envp_buf;
873 return @ptrCast([*:null]?[*:0]u8, envp_buf.ptr)[0..envp_count];
870874}
871875
872876pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) void {
......@@ -967,7 +971,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
967971
968972/// This is the same as `symlink` except the parameters are null-terminated pointers.
969973/// See also `symlink`.
970pub fn symlinkC(target_path: [*]const u8, sym_link_path: [*]const u8) SymLinkError!void {
974pub fn symlinkC(target_path: [*:0]const u8, sym_link_path: [*:0]const u8) SymLinkError!void {
971975 if (builtin.os == .windows) {
972976 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
973977 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
......@@ -999,7 +1003,7 @@ pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const
9991003 return symlinkatC(target_path_c, newdirfd, sym_link_path_c);
10001004}
10011005
1002pub fn symlinkatC(target_path: [*]const u8, newdirfd: fd_t, sym_link_path: [*]const u8) SymLinkError!void {
1006pub fn symlinkatC(target_path: [*:0]const u8, newdirfd: fd_t, sym_link_path: [*:0]const u8) SymLinkError!void {
10031007 switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) {
10041008 0 => return,
10051009 EFAULT => unreachable,
......@@ -1053,7 +1057,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {
10531057}
10541058
10551059/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.
1056pub fn unlinkC(file_path: [*]const u8) UnlinkError!void {
1060pub fn unlinkC(file_path: [*:0]const u8) UnlinkError!void {
10571061 if (builtin.os == .windows) {
10581062 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
10591063 return windows.DeleteFileW(&file_path_w);
......@@ -1093,7 +1097,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo
10931097}
10941098
10951099/// Same as `unlinkat` but `file_path` is a null-terminated string.
1096pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatError!void {
1100pub fn unlinkatC(dirfd: fd_t, file_path_c: [*:0]const u8, flags: u32) UnlinkatError!void {
10971101 if (builtin.os == .windows) {
10981102 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
10991103 return unlinkatW(dirfd, &file_path_w, flags);
......@@ -1122,7 +1126,7 @@ pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatErro
11221126}
11231127
11241128/// Same as `unlinkat` but `sub_path_w` is UTF16LE, NT prefixed. Windows only.
1125pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatError!void {
1129pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*:0]const u16, flags: u32) UnlinkatError!void {
11261130 const w = windows;
11271131
11281132 const want_rmdir_behavior = (flags & AT_REMOVEDIR) != 0;
......@@ -1217,7 +1221,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
12171221}
12181222
12191223/// Same as `rename` except the parameters are null-terminated byte arrays.
1220pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
1224pub fn renameC(old_path: [*:0]const u8, new_path: [*:0]const u8) RenameError!void {
12211225 if (builtin.os == .windows) {
12221226 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
12231227 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
......@@ -1249,7 +1253,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
12491253
12501254/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
12511255/// Assumes target is Windows.
1252pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) RenameError!void {
1256pub fn renameW(old_path: [*:0]const u16, new_path: [*:0]const u16) RenameError!void {
12531257 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
12541258 return windows.MoveFileExW(old_path, new_path, flags);
12551259}
......@@ -1283,7 +1287,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
12831287}
12841288
12851289/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.
1286pub fn mkdirC(dir_path: [*]const u8, mode: u32) MakeDirError!void {
1290pub fn mkdirC(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
12871291 if (builtin.os == .windows) {
12881292 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
12891293 return windows.CreateDirectoryW(&dir_path_w, null);
......@@ -1333,7 +1337,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
13331337}
13341338
13351339/// Same as `rmdir` except the parameter is null-terminated.
1336pub fn rmdirC(dir_path: [*]const u8) DeleteDirError!void {
1340pub fn rmdirC(dir_path: [*:0]const u8) DeleteDirError!void {
13371341 if (builtin.os == .windows) {
13381342 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
13391343 return windows.RemoveDirectoryW(&dir_path_w);
......@@ -1380,7 +1384,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
13801384}
13811385
13821386/// Same as `chdir` except the parameter is null-terminated.
1383pub fn chdirC(dir_path: [*]const u8) ChangeCurDirError!void {
1387pub fn chdirC(dir_path: [*:0]const u8) ChangeCurDirError!void {
13841388 if (builtin.os == .windows) {
13851389 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
13861390 @compileError("TODO implement chdir for Windows");
......@@ -1422,7 +1426,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
14221426}
14231427
14241428/// Same as `readlink` except `file_path` is null-terminated.
1425pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1429pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
14261430 if (builtin.os == .windows) {
14271431 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
14281432 @compileError("TODO implement readlink for Windows");
......@@ -1443,7 +1447,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
14431447 }
14441448}
14451449
1446pub fn readlinkatC(dirfd: fd_t, file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1450pub fn readlinkatC(dirfd: fd_t, file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
14471451 if (builtin.os == .windows) {
14481452 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
14491453 @compileError("TODO implement readlink for Windows");
......@@ -2130,7 +2134,7 @@ pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INoti
21302134}
21312135
21322136/// Same as `inotify_add_watch` except pathname is null-terminated.
2133pub fn inotify_add_watchC(inotify_fd: i32, pathname: [*]const u8, mask: u32) INotifyAddWatchError!i32 {
2137pub fn inotify_add_watchC(inotify_fd: i32, pathname: [*:0]const u8, mask: u32) INotifyAddWatchError!i32 {
21342138 const rc = system.inotify_add_watch(inotify_fd, pathname, mask);
21352139 switch (errno(rc)) {
21362140 0 => return @intCast(i32, rc),
......@@ -2287,7 +2291,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
22872291}
22882292
22892293/// Same as `access` except `path` is null-terminated.
2290pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
2294pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
22912295 if (builtin.os == .windows) {
22922296 const path_w = try windows.cStrToPrefixedFileW(path);
22932297 _ = try windows.GetFileAttributesW(&path_w);
......@@ -2314,7 +2318,7 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
23142318/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
23152319/// Otherwise use `access` or `accessC`.
23162320/// TODO currently this ignores `mode`.
2317pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!void {
2321pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!void {
23182322 const ret = try windows.GetFileAttributesW(path);
23192323 if (ret != windows.INVALID_FILE_ATTRIBUTES) {
23202324 return;
......@@ -2381,7 +2385,7 @@ pub fn sysctl(
23812385}
23822386
23832387pub fn sysctlbynameC(
2384 name: [*]const u8,
2388 name: [*:0]const u8,
23852389 oldp: ?*c_void,
23862390 oldlenp: ?*usize,
23872391 newp: ?*c_void,
......@@ -2563,7 +2567,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE
25632567}
25642568
25652569/// Same as `realpath` except `pathname` is null-terminated.
2566pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
2570pub fn realpathC(pathname: [*:0]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
25672571 if (builtin.os == .windows) {
25682572 const pathname_w = try windows.cStrToPrefixedFileW(pathname);
25692573 return realpathW(&pathname_w, out_buffer);
......@@ -2572,10 +2576,10 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
25722576 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);
25732577 defer close(fd);
25742578
2575 var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
2579 var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
25762580 const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
25772581
2578 return readlinkC(proc_path.ptr, out_buffer);
2582 return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
25792583 }
25802584 const result_path = std.c.realpath(pathname, out_buffer) orelse switch (std.c._errno().*) {
25812585 EINVAL => unreachable,
......@@ -2594,7 +2598,7 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
25942598}
25952599
25962600/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.
2597pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
2601pub fn realpathW(pathname: [*:0]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 {
25982602 const h_file = try windows.CreateFileW(
25992603 pathname,
26002604 windows.GENERIC_READ,
......@@ -2749,8 +2753,8 @@ pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
27492753
27502754/// Used to convert a slice to a null terminated slice on the stack.
27512755/// TODO https://github.com/ziglang/zig/issues/287
2752pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
2753 var path_with_null: [PATH_MAX]u8 = undefined;
2756pub fn toPosixPath(file_path: []const u8) ![PATH_MAX-1:0]u8 {
2757 var path_with_null: [PATH_MAX-1:0]u8 = undefined;
27542758 // >= rather than > to make room for the null byte
27552759 if (file_path.len >= PATH_MAX) return error.NameTooLong;
27562760 mem.copy(u8, &path_with_null, file_path);
......@@ -2855,7 +2859,7 @@ pub const GetHostNameError = error{PermissionDenied} || UnexpectedError;
28552859pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
28562860 if (builtin.link_libc) {
28572861 switch (errno(system.gethostname(name_buffer, name_buffer.len))) {
2858 0 => return mem.toSlice(u8, name_buffer),
2862 0 => return mem.toSlice(u8, @ptrCast([*:0]u8, name_buffer)),
28592863 EFAULT => unreachable,
28602864 ENAMETOOLONG => unreachable, // HOST_NAME_MAX prevents this
28612865 EPERM => return error.PermissionDenied,
lib/std/os/bits/darwin.zig+1-1
......@@ -1205,7 +1205,7 @@ pub const addrinfo = extern struct {
12051205 socktype: i32,
12061206 protocol: i32,
12071207 addrlen: socklen_t,
1208 canonname: ?[*]u8,
1208 canonname: ?[*:0]u8,
12091209 addr: ?*sockaddr,
12101210 next: ?*addrinfo,
12111211};
lib/std/os/bits/linux.zig+1-1
......@@ -1355,7 +1355,7 @@ pub const addrinfo = extern struct {
13551355 protocol: i32,
13561356 addrlen: socklen_t,
13571357 addr: ?*sockaddr,
1358 canonname: ?[*]u8,
1358 canonname: ?[*:0]u8,
13591359 next: ?*addrinfo,
13601360};
13611361
lib/std/os/wasi.zig+2-2
......@@ -19,13 +19,13 @@ comptime {
1919pub const iovec_t = iovec;
2020pub const ciovec_t = iovec_const;
2121
22pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t;
22pub extern "wasi_unstable" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t;
2323pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
2424
2525pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t;
2626pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t;
2727
28pub extern "wasi_unstable" fn environ_get(environ: [*]?[*]u8, environ_buf: [*]u8) errno_t;
28pub extern "wasi_unstable" fn environ_get(environ: [*]?[*:0]u8, environ_buf: [*]u8) errno_t;
2929pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t;
3030
3131pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t;
lib/std/os/windows.zig+8-8
......@@ -192,7 +192,7 @@ pub const FindFirstFileError = error{
192192};
193193
194194pub fn FindFirstFile(dir_path: []const u8, find_file_data: *WIN32_FIND_DATAW) FindFirstFileError!HANDLE {
195 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, [_]u16{ '\\', '*', 0 });
195 const dir_path_w = try sliceToPrefixedSuffixedFileW(dir_path, [_]u16{ '\\', '*'});
196196 const handle = kernel32.FindFirstFileW(&dir_path_w, find_file_data);
197197
198198 if (handle == INVALID_HANDLE_VALUE) {
......@@ -919,18 +919,18 @@ pub fn nanoSecondsToFileTime(ns: i64) FILETIME {
919919 };
920920}
921921
922pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {
922pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
923923 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
924924}
925925
926pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {
927 return sliceToPrefixedSuffixedFileW(s, [_]u16{0});
926pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE:0]u16 {
927 return sliceToPrefixedSuffixedFileW(s, &[_]u16{});
928928}
929929
930930/// Assumes an absolute path.
931pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {
931pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE:0]u16 {
932932 // TODO https://github.com/ziglang/zig/issues/2765
933 var result: [PATH_MAX_WIDE + 1]u16 = undefined;
933 var result: [PATH_MAX_WIDE:0]u16 = undefined;
934934
935935 const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: {
936936 const prefix = [_]u16{ '\\', '?', '?', '\\' };
......@@ -945,9 +945,9 @@ pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {
945945
946946}
947947
948pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 {
948pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len:0]u16 {
949949 // TODO https://github.com/ziglang/zig/issues/2765
950 var result: [PATH_MAX_WIDE + suffix.len]u16 = undefined;
950 var result: [PATH_MAX_WIDE + suffix.len:0]u16 = undefined;
951951 // > File I/O functions in the Windows API convert "/" to "\" as part of
952952 // > converting the name to an NT-style name, except when using the "\\?\"
953953 // > prefix as detailed in the following sections.
lib/std/process.zig+2-2
......@@ -77,7 +77,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
7777
7878 // TODO: Verify that the documentation is incorrect
7979 // https://github.com/WebAssembly/WASI/issues/27
80 var environ = try allocator.alloc(?[*]u8, environ_count + 1);
80 var environ = try allocator.alloc(?[*:0]u8, environ_count + 1);
8181 defer allocator.free(environ);
8282 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
8383 defer allocator.free(environ_buf);
......@@ -397,7 +397,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
397397 return os.unexpectedErrno(args_sizes_get_ret);
398398 }
399399
400 var argv = try allocator.alloc([*]u8, count);
400 var argv = try allocator.alloc([*:0]u8, count);
401401 defer allocator.free(argv);
402402
403403 var argv_buf = try allocator.alloc(u8, buf_size);
src/analyze.cpp+1-1
......@@ -6550,7 +6550,7 @@ static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprVal
65506550}
65516551
65526552bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
6553 assert(a->type->id == b->type->id);
6553 if (a->type->id != b->type->id) return false;
65546554 assert(a->special == ConstValSpecialStatic);
65556555 assert(b->special == ConstValSpecialStatic);
65566556 if (a->type == b->type) {