authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-25 02:20:08-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-11-25 02:20:08-05:00
log5a98dd42b38b9188cfb96c9ab57dc91af923029f
tree5b48dea38aeb28cf82b9ee98092bad4aea004d90
parent69b780647abd14f0809a58006242397f3e94ac51
parent321726465d3151d80e651b0c3001177a3ef53fff
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3728 from ziglang/null-terminated-pointers

sentinel-terminated pointers

80 files changed, 2589 insertions(+), 1600 deletions(-)

doc/docgen.zig-2
......@@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
954954 .AngleBracketAngleBracketRight,
955955 .AngleBracketAngleBracketRightEqual,
956956 .Tilde,
957 .BracketStarBracket,
958 .BracketStarCBracket,
959957 => try writeEscaped(out, src[token.start..token.end]),
960958
961959 .Invalid, .Invalid_ampersands => return parseError(
doc/langref.html.in+89-59
......@@ -546,7 +546,11 @@ pub fn main() void {
546546 {#header_close#}
547547 {#header_open|String Literals and Character Literals#}
548548 <p>
549 String literals are UTF-8 encoded byte arrays.
549 String literals are single-item constant {#link|Pointers#} to null-terminated UTF-8 encoded byte arrays.
550 The type of string literals encodes both the length, and the fact that they are null-terminated,
551 and thus they can be {#link|coerced|Type Coercion#} to both {#link|Slices#} and
552 {#link|Null-Terminated Pointers|Sentinel-Terminated Pointers#}.
553 Dereferencing string literals converts them to {#link|Arrays#}.
550554 </p>
551555 <p>
552556 Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as
......@@ -558,20 +562,15 @@ const assert = @import("std").debug.assert;
558562const mem = @import("std").mem;
559563
560564test "string literals" {
561 // In Zig a string literal is an array of bytes.
562 const normal_bytes = "hello";
563 assert(@typeOf(normal_bytes) == [5]u8);
564 assert(normal_bytes.len == 5);
565 assert(normal_bytes[1] == 'e');
565 const bytes = "hello";
566 assert(@typeOf(bytes) == *const [5:0]u8);
567 assert(bytes.len == 5);
568 assert(bytes[1] == 'e');
569 assert(bytes[5] == 0);
566570 assert('e' == '\x65');
567571 assert('\u{1f4a9}' == 128169);
568572 assert('💯' == 128175);
569573 assert(mem.eql(u8, "hello", "h\x65llo"));
570
571 // A C string literal is a null terminated pointer.
572 const null_terminated_bytes = c"hello";
573 assert(@typeOf(null_terminated_bytes) == [*]const u8);
574 assert(null_terminated_bytes[5] == 0);
575574}
576575 {#code_end#}
577576 {#see_also|Arrays|Zig Test|Source Encoding#}
......@@ -641,23 +640,6 @@ const hello_world_in_c =
641640 \\}
642641;
643642 {#code_end#}
644 <p>
645 For a multiline C string literal, prepend <code>c</code> to each {#syntax#}\\{#endsyntax#}:
646 </p>
647 {#code_begin|syntax#}
648const c_string_literal =
649 c\\#include <stdio.h>
650 c\\
651 c\\int main(int argc, char **argv) {
652 c\\ printf("hello world\n");
653 c\\ return 0;
654 c\\}
655;
656 {#code_end#}
657 <p>
658 In this example the variable {#syntax#}c_string_literal{#endsyntax#} has type {#syntax#}[*]const u8{#endsyntax#} and
659 has a terminating null byte.
660 </p>
661643 {#see_also|@embedFile#}
662644 {#header_close#}
663645 {#header_close#}
......@@ -1638,12 +1620,11 @@ comptime {
16381620 assert(message.len == 5);
16391621}
16401622
1641// a string literal is an array literal
1642const same_message = "hello";
1623// A string literal is a pointer to an array literal.
1624const same_message = "hello".*;
16431625
16441626comptime {
16451627 assert(mem.eql(u8, message, same_message));
1646 assert(@typeOf(message) == @typeOf(same_message));
16471628}
16481629
16491630test "iterate over an array" {
......@@ -1799,6 +1780,26 @@ test "multidimensional arrays" {
17991780}
18001781 {#code_end#}
18011782 {#header_close#}
1783
1784 {#header_open|Sentinel-Terminated Arrays#}
1785 <p>
1786 The syntax {#syntax#}[N:x]T{#endsyntax#} describes an array which has a sentinel element at the
1787 index corresponding to {#syntax#}len{#endsyntax#}.
1788 </p>
1789 {#code_begin|test|null_terminated_array#}
1790const std = @import("std");
1791const assert = std.debug.assert;
1792
1793test "null terminated array" {
1794 const array = [_:0]u8 {1, 2, 3, 4};
1795
1796 assert(@typeOf(array) == [4:0]u8);
1797 assert(array.len == 4);
1798 assert(array[4] == 0);
1799}
1800 {#code_end#}
1801 {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Slices#}
1802 {#header_close#}
18021803 {#header_close#}
18031804
18041805 {#header_open|Vectors#}
......@@ -1899,7 +1900,7 @@ test "pointer array access" {
18991900}
19001901 {#code_end#}
19011902 <p>
1902 In Zig, we prefer slices over pointers to null-terminated arrays.
1903 In Zig, we generally prefer {#link|Slices#} rather than {#link|Sentinel-Terminated Pointers#}.
19031904 You can turn an array or pointer into a slice using slice syntax.
19041905 </p>
19051906 <p>
......@@ -2111,6 +2112,29 @@ test "allowzero" {
21112112}
21122113 {#code_end#}
21132114 {#header_close#}
2115
2116 {#header_open|Sentinel-Terminated Pointers#}
2117 <p>
2118 The syntax {#syntax#}[*:x]T{#endsyntax#} describes a pointer that
2119 has a length determined by a sentinel value. This provides protection
2120 against buffer overflow and overreads.
2121 </p>
2122 {#code_begin|exe_build_err#}
2123const std = @import("std");
2124
2125// This is also available as `std.c.printf`.
2126pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
2127
2128pub fn main() anyerror!void {
2129 _ = printf("Hello, world!\n"); // OK
2130
2131 const msg = "Hello, world!\n";
2132 const non_null_terminated_msg: [msg.len]u8 = msg.*;
2133 _ = printf(&non_null_terminated_msg);
2134}
2135 {#code_end#}
2136 {#see_also|Sentinel-Terminated Slices|Sentinel-Terminated Arrays#}
2137 {#header_close#}
21142138 {#header_close#}
21152139
21162140 {#header_open|Slices#}
......@@ -2194,7 +2218,29 @@ test "slice widening" {
21942218}
21952219 {#code_end#}
21962220 {#see_also|Pointers|for|Arrays#}
2221
2222 {#header_open|Sentinel-Terminated Slices#}
2223 <p>
2224 The syntax {#syntax#}[:x]T{#endsyntax#} is a slice which has a runtime known length
2225 and also guarantees a sentinel value at the element indexed by the length. The type does not
2226 guarantee that there are no sentinel elements before that. Sentinel-terminated slices allow element
2227 access to the {#syntax#}len{#endsyntax#} index.
2228 </p>
2229 {#code_begin|test|null_terminated_slice#}
2230const std = @import("std");
2231const assert = std.debug.assert;
2232
2233test "null terminated slice" {
2234 const slice: [:0]const u8 = "hello";
2235
2236 assert(slice.len == 5);
2237 assert(slice[5] == 0);
2238}
2239 {#code_end#}
2240 {#see_also|Sentinel-Terminated Pointers|Sentinel-Terminated Arrays#}
21972241 {#header_close#}
2242 {#header_close#}
2243
21982244 {#header_open|struct#}
21992245 {#code_begin|test|structs#}
22002246// Declare a struct.
......@@ -4817,9 +4863,9 @@ const assert = std.debug.assert;
48174863const mem = std.mem;
48184864
48194865test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
4820 const window_name = [1][*]const u8{c"window name"};
4866 const window_name = [1][*]const u8{"window name"};
48214867 const x: [*]const ?[*]const u8 = &window_name;
4822 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"));
48234869}
48244870 {#code_end#}
48254871 {#header_close#}
......@@ -4859,7 +4905,7 @@ test "float widening" {
48594905 {#code_end#}
48604906 {#header_close#}
48614907 {#header_open|Type Coercion: Arrays and Pointers#}
4862 {#code_begin|test#}
4908 {#code_begin|test|coerce_arrays_and_ptrs#}
48634909const std = @import("std");
48644910const assert = std.debug.assert;
48654911
......@@ -4898,7 +4944,7 @@ test "[N]T to ?[]const T" {
48984944
48994945// In this cast, the array length becomes the slice length.
49004946test "*[N]T to []T" {
4901 var buf: [5]u8 = "hello";
4947 var buf: [5]u8 = "hello".*;
49024948 const x: []u8 = &buf;
49034949 assert(std.mem.eql(u8, x, "hello"));
49044950
......@@ -4910,7 +4956,7 @@ test "*[N]T to []T" {
49104956// Single-item pointers to arrays can be coerced to
49114957// unknown length pointers.
49124958test "*[N]T to [*]T" {
4913 var buf: [5]u8 = "hello";
4959 var buf: [5]u8 = "hello".*;
49144960 const x: [*]u8 = &buf;
49154961 assert(x[4] == 'o');
49164962 // x[5] would be an uncaught out of bounds pointer dereference!
......@@ -4918,7 +4964,7 @@ test "*[N]T to [*]T" {
49184964
49194965// Likewise, it works when the destination type is an optional.
49204966test "*[N]T to ?[*]T" {
4921 var buf: [5]u8 = "hello";
4967 var buf: [5]u8 = "hello".*;
49224968 const x: ?[*]u8 = &buf;
49234969 assert(x.?[4] == 'o');
49244970}
......@@ -5089,7 +5135,7 @@ test "coercion of zero bit types" {
50895135 This kind of type resolution chooses a type that all peer types can coerce into. Here are
50905136 some examples:
50915137 </p>
5092 {#code_begin|test#}
5138 {#code_begin|test|peer_type_resolution#}
50935139const std = @import("std");
50945140const assert = std.debug.assert;
50955141const mem = std.mem;
......@@ -5156,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
51565202}
51575203test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
51585204 {
5159 var data = "hi";
5205 var data = "hi".*;
51605206 const slice = data[0..];
51615207 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
51625208 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
51635209 }
51645210 comptime {
5165 var data = "hi";
5211 var data = "hi".*;
51665212 const slice = data[0..];
51675213 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
51685214 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
......@@ -8627,7 +8673,7 @@ pub fn main() void {
86278673 <p>At compile-time:</p>
86288674 {#code_begin|test_err|index 5 outside array of size 5#}
86298675comptime {
8630 const array = "hello";
8676 const array: [5]u8 = "hello".*;
86318677 const garbage = array[5];
86328678}
86338679 {#code_end#}
......@@ -9603,22 +9649,6 @@ test "assert in release fast mode" {
96039649 </ul>
96049650 {#see_also|Primitive Types#}
96059651 {#header_close#}
9606 {#header_open|C String Literals#}
9607 {#code_begin|exe#}
9608 {#link_libc#}
9609extern fn puts([*]const u8) void;
9610
9611pub fn main() void {
9612 puts(c"this has a null terminator");
9613 puts(
9614 c\\and so
9615 c\\does this
9616 c\\multiline C string literal
9617 );
9618}
9619 {#code_end#}
9620 {#see_also|String Literals and Character Literals#}
9621 {#header_close#}
96229652
96239653 {#header_open|Import from C Header File#}
96249654 <p>
......@@ -9633,7 +9663,7 @@ const c = @cImport({
96339663 @cInclude("stdio.h");
96349664});
96359665pub fn main() void {
9636 _ = c.printf(c"hello\n");
9666 _ = c.printf("hello\n");
96379667}
96389668 {#code_end#}
96399669 <p>
lib/std/buffer.zig+2-7
......@@ -72,11 +72,11 @@ pub const Buffer = struct {
7272 self.list.deinit();
7373 }
7474
75 pub fn toSlice(self: Buffer) []u8 {
75 pub fn toSlice(self: Buffer) [:0]u8 {
7676 return self.list.toSlice()[0..self.len()];
7777 }
7878
79 pub fn toSliceConst(self: Buffer) []const u8 {
79 pub fn toSliceConst(self: Buffer) [:0]const u8 {
8080 return self.list.toSliceConst()[0..self.len()];
8181 }
8282
......@@ -131,11 +131,6 @@ pub const Buffer = struct {
131131 try self.resize(m.len);
132132 mem.copy(u8, self.list.toSlice(), m);
133133 }
134
135 /// For passing to C functions.
136 pub fn ptr(self: Buffer) [*]u8 {
137 return self.list.items.ptr;
138 }
139134};
140135
141136test "simple Buffer" {
lib/std/builtin.zig+8
......@@ -144,6 +144,10 @@ pub const TypeInfo = union(enum) {
144144 alignment: comptime_int,
145145 child: type,
146146 is_allowzero: bool,
147 /// The type of the sentinel is the element type of the pointer, which is
148 /// the value of the `child` field in this struct. However there is no way
149 /// to refer to that type here, so we use `var`.
150 sentinel: var,
147151
148152 /// This data structure is used by the Zig language code generation and
149153 /// therefore must be kept in sync with the compiler implementation.
......@@ -160,6 +164,10 @@ pub const TypeInfo = union(enum) {
160164 pub const Array = struct {
161165 len: comptime_int,
162166 child: type,
167 /// The type of the sentinel is the element type of the array, which is
168 /// the value of the `child` field in this struct. However there is no way
169 /// to refer to that type here, so we use `var`.
170 sentinel: var,
163171 };
164172
165173 /// This data structure is used by the Zig language code generation and
lib/std/c.zig+3-3
......@@ -63,7 +63,7 @@ pub extern "c" fn fclose(stream: *FILE) c_int;
6363pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
6464pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
6565
66pub extern "c" fn printf(format: [*]const u8, ...) c_int;
66pub extern "c" fn printf(format: [*:0]const u8, ...) c_int;
6767pub extern "c" fn abort() noreturn;
6868pub extern "c" fn exit(code: c_int) noreturn;
6969pub extern "c" fn isatty(fd: fd_t) c_int;
......@@ -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;
......@@ -110,7 +110,7 @@ pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
110110pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
111111pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;
112112pub extern "c" fn rmdir(path: [*]const u8) c_int;
113pub extern "c" fn getenv(name: [*]const u8) ?[*]u8;
113pub extern "c" fn getenv(name: [*:0]const u8) ?[*:0]u8;
114114pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
115115pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
116116pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;
lib/std/child_process.zig+2-1
......@@ -330,7 +330,7 @@ pub const ChildProcess = struct {
330330
331331 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
332332 const dev_null_fd = if (any_ignore)
333 os.openC(c"/dev/null", os.O_RDWR, 0) catch |err| switch (err) {
333 os.openC("/dev/null", os.O_RDWR, 0) catch |err| switch (err) {
334334 error.PathAlreadyExists => unreachable,
335335 error.NoSpaceLeft => unreachable,
336336 error.FileTooBig => unreachable,
......@@ -441,6 +441,7 @@ pub const ChildProcess = struct {
441441
442442 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
443443
444 // TODO use CreateFileW here since we are using a string literal for the path
444445 const nul_handle = if (any_ignore)
445446 windows.CreateFile(
446447 "NUL",
lib/std/crypto/x25519.zig+6-6
......@@ -610,8 +610,8 @@ test "x25519 rfc7748 vector2" {
610610}
611611
612612test "x25519 rfc7748 one iteration" {
613 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
614 const expected_output = "\x42\x2c\x8e\x7a\x62\x27\xd7\xbc\xa1\x35\x0b\x3e\x2b\xb7\x27\x9f\x78\x97\xb8\x7b\xb6\x85\x4b\x78\x3c\x60\xe8\x03\x11\xae\x30\x79";
613 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*;
614 const expected_output = "\x42\x2c\x8e\x7a\x62\x27\xd7\xbc\xa1\x35\x0b\x3e\x2b\xb7\x27\x9f\x78\x97\xb8\x7b\xb6\x85\x4b\x78\x3c\x60\xe8\x03\x11\xae\x30\x79".*;
615615
616616 var k: [32]u8 = initial_value;
617617 var u: [32]u8 = initial_value;
......@@ -634,8 +634,8 @@ test "x25519 rfc7748 1,000 iterations" {
634634 return error.SkipZigTest;
635635 }
636636
637 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
638 const expected_output = "\x68\x4c\xf5\x9b\xa8\x33\x09\x55\x28\x00\xef\x56\x6f\x2f\x4d\x3c\x1c\x38\x87\xc4\x93\x60\xe3\x87\x5f\x2e\xb9\x4d\x99\x53\x2c\x51";
637 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*;
638 const expected_output = "\x68\x4c\xf5\x9b\xa8\x33\x09\x55\x28\x00\xef\x56\x6f\x2f\x4d\x3c\x1c\x38\x87\xc4\x93\x60\xe3\x87\x5f\x2e\xb9\x4d\x99\x53\x2c\x51".*;
639639
640640 var k: [32]u8 = initial_value;
641641 var u: [32]u8 = initial_value;
......@@ -657,8 +657,8 @@ test "x25519 rfc7748 1,000,000 iterations" {
657657 return error.SkipZigTest;
658658 }
659659
660 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
661 const expected_output = "\x7c\x39\x11\xe0\xab\x25\x86\xfd\x86\x44\x97\x29\x7e\x57\x5e\x6f\x3b\xc6\x01\xc0\x88\x3c\x30\xdf\x5f\x4d\xd2\xd2\x4f\x66\x54\x24";
660 const initial_value = "\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*;
661 const expected_output = "\x7c\x39\x11\xe0\xab\x25\x86\xfd\x86\x44\x97\x29\x7e\x57\x5e\x6f\x3b\xc6\x01\xc0\x88\x3c\x30\xdf\x5f\x4d\xd2\xd2\x4f\x66\x54\x24".*;
662662
663663 var k: [32]u8 = initial_value;
664664 var u: [32]u8 = initial_value;
lib/std/cstr.zig+2-2
......@@ -27,8 +27,8 @@ test "cstr fns" {
2727}
2828
2929fn testCStrFnsImpl() void {
30 testing.expect(cmp(c"aoeu", c"aoez") == -1);
31 testing.expect(mem.len(u8, c"123456789") == 9);
30 testing.expect(cmp("aoeu", "aoez") == -1);
31 testing.expect(mem.len(u8, "123456789") == 9);
3232}
3333
3434/// Returns a mutable slice with 1 more byte of length which is a null byte.
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/fmt.zig+55-57
......@@ -1,8 +1,6 @@
11const std = @import("std.zig");
22const math = std.math;
3const debug = std.debug;
4const assert = debug.assert;
5const testing = std.testing;
3const assert = std.debug.assert;
64const mem = std.mem;
75const builtin = @import("builtin");
86const errol = @import("fmt/errol.zig");
......@@ -36,7 +34,7 @@ fn nextArg(comptime used_pos_args: *u32, comptime maybe_pos_arg: ?comptime_int,
3634
3735fn peekIsAlign(comptime fmt: []const u8) bool {
3836 // Should only be called during a state transition to the format segment.
39 std.debug.assert(fmt[0] == ':');
37 comptime assert(fmt[0] == ':');
4038
4139 inline for (([_]u8{ 1, 2 })[0..]) |i| {
4240 if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {
......@@ -1009,13 +1007,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
10091007}
10101008
10111009test "parseInt" {
1012 testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
1013 testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
1014 testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
1015 testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
1016 testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
1017 testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
1018 testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
1010 std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
1011 std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
1012 std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
1013 std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
1014 std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
1015 std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
1016 std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
10191017}
10201018
10211019const ParseUnsignedError = error{
......@@ -1040,30 +1038,30 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
10401038}
10411039
10421040test "parseUnsigned" {
1043 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
1044 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
1045 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
1041 std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
1042 std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
1043 std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
10461044
1047 testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
1048 testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
1045 std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
1046 std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
10491047
1050 testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
1048 std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
10511049
1052 testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
1053 testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
1050 std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
1051 std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
10541052
1055 testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
1056 testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
1053 std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
1054 std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
10571055
1058 testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
1056 std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
10591057
10601058 // these numbers should fit even though the radix itself doesn't fit in the destination type
1061 testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
1062 testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
1063 testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
1064 testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
1065 testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
1066 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
1059 std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
1060 std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
1061 std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
1062 std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
1063 std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
1064 std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
10671065}
10681066
10691067pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
......@@ -1134,19 +1132,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
11341132test "bufPrintInt" {
11351133 var buffer: [100]u8 = undefined;
11361134 const buf = buffer[0..];
1137 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110"));
1138 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}), "-12345678"));
1139 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}), "-bc614e"));
1140 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}), "-BC614E"));
1135 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110"));
1136 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}), "-12345678"));
1137 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}), "-bc614e"));
1138 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}), "-BC614E"));
11411139
1142 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}), "12345678"));
1140 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}), "12345678"));
11431141
1144 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }), " 666"));
1145 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234"));
1146 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234"));
1142 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }), " 666"));
1143 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234"));
1144 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234"));
11471145
1148 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }), "+42"));
1149 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42"));
1146 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }), "+42"));
1147 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42"));
11501148}
11511149
11521150fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
......@@ -1163,7 +1161,7 @@ test "parse u64 digit too big" {
11631161
11641162test "parse unsigned comptime" {
11651163 comptime {
1166 testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
1164 std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
11671165 }
11681166}
11691167
......@@ -1218,23 +1216,23 @@ test "buffer" {
12181216 var context = BufPrintContext{ .remaining = buf1[0..] };
12191217 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
12201218 var res = buf1[0 .. buf1.len - context.remaining.len];
1221 testing.expect(mem.eql(u8, res, "1234"));
1219 std.testing.expect(mem.eql(u8, res, "1234"));
12221220
12231221 context = BufPrintContext{ .remaining = buf1[0..] };
12241222 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
12251223 res = buf1[0 .. buf1.len - context.remaining.len];
1226 testing.expect(mem.eql(u8, res, "a"));
1224 std.testing.expect(mem.eql(u8, res, "a"));
12271225
12281226 context = BufPrintContext{ .remaining = buf1[0..] };
12291227 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
12301228 res = buf1[0 .. buf1.len - context.remaining.len];
1231 testing.expect(mem.eql(u8, res, "1100"));
1229 std.testing.expect(mem.eql(u8, res, "1100"));
12321230 }
12331231}
12341232
12351233test "array" {
12361234 {
1237 const value: [3]u8 = "abc";
1235 const value: [3]u8 = "abc".*;
12381236 try testFmt("array: abc\n", "array: {}\n", value);
12391237 try testFmt("array: abc\n", "array: {}\n", &value);
12401238
......@@ -1278,8 +1276,8 @@ test "pointer" {
12781276}
12791277
12801278test "cstr" {
1281 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
1282 try testFmt("cstr: Test C \n", "cstr: {s:10}\n", c"Test C");
1279 try testFmt("cstr: Test C\n", "cstr: {s}\n", "Test C");
1280 try testFmt("cstr: Test C \n", "cstr: {s:10}\n", "Test C");
12831281}
12841282
12851283test "filesize" {
......@@ -1479,10 +1477,10 @@ test "union" {
14791477
14801478 var buf: [100]u8 = undefined;
14811479 const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
1482 testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
1480 std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
14831481
14841482 const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
1485 testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
1483 std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
14861484}
14871485
14881486test "enum" {
......@@ -1569,11 +1567,11 @@ pub fn trim(buf: []const u8) []const u8 {
15691567}
15701568
15711569test "trim" {
1572 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1573 testing.expect(mem.eql(u8, "", trim(" ")));
1574 testing.expect(mem.eql(u8, "", trim("")));
1575 testing.expect(mem.eql(u8, "abc", trim(" abc")));
1576 testing.expect(mem.eql(u8, "abc", trim("abc ")));
1570 std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1571 std.testing.expect(mem.eql(u8, "", trim(" ")));
1572 std.testing.expect(mem.eql(u8, "", trim("")));
1573 std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
1574 std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
15771575}
15781576
15791577pub fn isWhiteSpace(byte: u8) bool {
......@@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" {
16071605
16081606 var buf = try std.Buffer.init(std.debug.global_allocator, "");
16091607 try formatIntValue(value, "", FormatOptions{}, &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
1610 assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));
1608 std.testing.expect(mem.eql(u8, buf.toSlice(), "123456789123456789"));
16111609}
16121610
16131611test "formatType max_depth" {
......@@ -1661,19 +1659,19 @@ test "formatType max_depth" {
16611659
16621660 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
16631661 try formatType(inst, "", FormatOptions{}, &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
1664 assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
1662 std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
16651663
16661664 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
16671665 try formatType(inst, "", FormatOptions{}, &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
1668 assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
1666 std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
16691667
16701668 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
16711669 try formatType(inst, "", FormatOptions{}, &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
1672 assert(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
1670 std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
16731671
16741672 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
16751673 try formatType(inst, "", FormatOptions{}, &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
1676 assert(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
1674 std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
16771675}
16781676
16791677test "positional" {
lib/std/fs.zig+29-27
......@@ -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
......@@ -533,7 +534,7 @@ pub const Dir = struct {
533534 const next_index = self.index + linux_entry.reclen();
534535 self.index = next_index;
535536
536 const name = mem.toSlice(u8, @ptrCast([*]u8, &linux_entry.d_name));
537 const name = mem.toSlice(u8, @ptrCast([*:0]u8, &linux_entry.d_name));
537538
538539 // skip . and .. entries
539540 if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
......@@ -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
......@@ -1240,7 +1241,7 @@ pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfE
12401241
12411242pub fn openSelfExe() OpenSelfExeError!File {
12421243 if (builtin.os == .linux) {
1243 return File.openReadC(c"/proc/self/exe");
1244 return File.openReadC("/proc/self/exe");
12441245 }
12451246 if (builtin.os == .windows) {
12461247 const wide_slice = selfExePathW();
......@@ -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,23 +1279,23 @@ 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) {
1283 .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
1285 .linux => return os.readlinkC("/proc/self/exe", out_buffer),
12841286 .freebsd, .dragonfly => {
12851287 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
12861288 var out_len: usize = out_buffer.len;
12871289 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
12881290 // TODO could this slice from 0 to out_len instead?
1289 return mem.toSlice(u8, out_buffer);
1291 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
12901292 },
12911293 .netbsd => {
12921294 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
12931295 var out_len: usize = out_buffer.len;
12941296 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
12951297 // TODO could this slice from 0 to out_len instead?
1296 return mem.toSlice(u8, out_buffer);
1298 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
12971299 },
12981300 .windows => {
12991301 const utf16le_slice = selfExePathW();
......@@ -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.
......@@ -1326,7 +1328,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const
13261328 // the file path looks something like `/a/b/c/exe (deleted)`
13271329 // This path cannot be opened, but it's valid for determining the directory
13281330 // the executable was in when it was run.
1329 const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
1331 const full_exe_path = try os.readlinkC("/proc/self/exe", out_buffer);
13301332 // Assume that /proc/self/exe has an absolute path, and therefore dirname
13311333 // will not return null.
13321334 return path.dirname(full_exe_path).?;
lib/std/fs/file.zig+8-8
......@@ -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
......@@ -172,7 +172,7 @@ pub const File = struct {
172172 if (self.isTty()) {
173173 if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) {
174174 // Use getenvC to workaround https://github.com/ziglang/zig/issues/3511
175 if (os.getenvC(c"TERM")) |term| {
175 if (os.getenvC("TERM")) |term| {
176176 if (std.mem.eql(u8, term, "dumb"))
177177 return false;
178178 }
lib/std/fs/path.zig+1-1
......@@ -394,7 +394,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
394394 }
395395
396396 // determine which disk designator we will result with, if any
397 var result_drive_buf = "_:";
397 var result_drive_buf = "_:".*;
398398 var result_disk_designator: []const u8 = "";
399399 var have_drive_kind = WindowsPath.Kind.None;
400400 var have_abs_path = false;
lib/std/hash/siphash.zig+128-128
......@@ -202,70 +202,70 @@ const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x
202202
203203test "siphash64-2-4 sanity" {
204204 const vectors = [_][8]u8{
205 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
206 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
207 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
208 "\x2d\x7e\xfb\xd7\x96\x66\x67\x85",
209 "\xb7\x87\x71\x27\xe0\x94\x27\xcf",
210 "\x8d\xa6\x99\xcd\x64\x55\x76\x18",
211 "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb",
212 "\x37\xd1\x01\x8b\xf5\x00\x02\xab",
213 "\x62\x24\x93\x9a\x79\xf5\xf5\x93",
214 "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e",
215 "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a",
216 "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4",
217 "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75",
218 "\x90\x3d\x84\xc0\x27\x56\xea\x14",
219 "\xee\xf2\x7a\x8e\x90\xca\x23\xf7",
220 "\xe5\x45\xbe\x49\x61\xca\x29\xa1",
221 "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f",
222 "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69",
223 "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b",
224 "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb",
225 "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe",
226 "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0",
227 "\x88\x3e\xa3\xe3\x95\x67\x53\x93",
228 "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8",
229 "\x94\xaf\x49\xf6\xc6\x50\xad\xb8",
230 "\xea\xb8\x85\x8a\xde\x92\xe1\xbc",
231 "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17",
232 "\xad\xcf\x6b\x07\x63\x61\x2e\x2f",
233 "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde",
234 "\x71\x65\x95\x87\x66\x50\xa2\xa6",
235 "\x28\xef\x49\x5c\x53\xa3\x87\xad",
236 "\x42\xc3\x41\xd8\xfa\x92\xd8\x32",
237 "\xce\x7c\xf2\x72\x2f\x51\x27\x71",
238 "\xe3\x78\x59\xf9\x46\x23\xf3\xa7",
239 "\x38\x12\x05\xbb\x1a\xb0\xe0\x12",
240 "\xae\x97\xa1\x0f\xd4\x34\xe0\x15",
241 "\xb4\xa3\x15\x08\xbe\xff\x4d\x31",
242 "\x81\x39\x62\x29\xf0\x90\x79\x02",
243 "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca",
244 "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a",
245 "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e",
246 "\x92\x59\x58\xfc\xd6\x42\x0c\xad",
247 "\xa9\x15\xc2\x9b\xc8\x06\x73\x18",
248 "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4",
249 "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9",
250 "\x87\x57\x75\x19\x04\x8f\x53\xa9",
251 "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb",
252 "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0",
253 "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6",
254 "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7",
255 "\x72\xfe\x52\x97\x5a\x43\x64\xee",
256 "\x5a\x16\x45\xb2\x76\xd5\x92\xa1",
257 "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a",
258 "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81",
259 "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f",
260 "\x99\x24\xa4\x3c\xc1\x31\x57\x24",
261 "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7",
262 "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea",
263 "\x13\x50\x79\xa3\x23\x1c\xe6\x60",
264 "\x93\x2b\x28\x46\xe4\xd7\x06\x66",
265 "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c",
266 "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f",
267 "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5",
268 "\x72\x45\x06\xeb\x4c\x32\x8a\x95",
205 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72".*, // ""
206 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74".*, // "\x00"
207 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d".*, // "\x00\x01" ... etc
208 "\x2d\x7e\xfb\xd7\x96\x66\x67\x85".*,
209 "\xb7\x87\x71\x27\xe0\x94\x27\xcf".*,
210 "\x8d\xa6\x99\xcd\x64\x55\x76\x18".*,
211 "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb".*,
212 "\x37\xd1\x01\x8b\xf5\x00\x02\xab".*,
213 "\x62\x24\x93\x9a\x79\xf5\xf5\x93".*,
214 "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e".*,
215 "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a".*,
216 "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4".*,
217 "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75".*,
218 "\x90\x3d\x84\xc0\x27\x56\xea\x14".*,
219 "\xee\xf2\x7a\x8e\x90\xca\x23\xf7".*,
220 "\xe5\x45\xbe\x49\x61\xca\x29\xa1".*,
221 "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f".*,
222 "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69".*,
223 "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b".*,
224 "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb".*,
225 "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe".*,
226 "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0".*,
227 "\x88\x3e\xa3\xe3\x95\x67\x53\x93".*,
228 "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8".*,
229 "\x94\xaf\x49\xf6\xc6\x50\xad\xb8".*,
230 "\xea\xb8\x85\x8a\xde\x92\xe1\xbc".*,
231 "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17".*,
232 "\xad\xcf\x6b\x07\x63\x61\x2e\x2f".*,
233 "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde".*,
234 "\x71\x65\x95\x87\x66\x50\xa2\xa6".*,
235 "\x28\xef\x49\x5c\x53\xa3\x87\xad".*,
236 "\x42\xc3\x41\xd8\xfa\x92\xd8\x32".*,
237 "\xce\x7c\xf2\x72\x2f\x51\x27\x71".*,
238 "\xe3\x78\x59\xf9\x46\x23\xf3\xa7".*,
239 "\x38\x12\x05\xbb\x1a\xb0\xe0\x12".*,
240 "\xae\x97\xa1\x0f\xd4\x34\xe0\x15".*,
241 "\xb4\xa3\x15\x08\xbe\xff\x4d\x31".*,
242 "\x81\x39\x62\x29\xf0\x90\x79\x02".*,
243 "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca".*,
244 "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a".*,
245 "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e".*,
246 "\x92\x59\x58\xfc\xd6\x42\x0c\xad".*,
247 "\xa9\x15\xc2\x9b\xc8\x06\x73\x18".*,
248 "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4".*,
249 "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9".*,
250 "\x87\x57\x75\x19\x04\x8f\x53\xa9".*,
251 "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb".*,
252 "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0".*,
253 "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6".*,
254 "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7".*,
255 "\x72\xfe\x52\x97\x5a\x43\x64\xee".*,
256 "\x5a\x16\x45\xb2\x76\xd5\x92\xa1".*,
257 "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a".*,
258 "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81".*,
259 "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f".*,
260 "\x99\x24\xa4\x3c\xc1\x31\x57\x24".*,
261 "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7".*,
262 "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea".*,
263 "\x13\x50\x79\xa3\x23\x1c\xe6\x60".*,
264 "\x93\x2b\x28\x46\xe4\xd7\x06\x66".*,
265 "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c".*,
266 "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f".*,
267 "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5".*,
268 "\x72\x45\x06\xeb\x4c\x32\x8a\x95".*,
269269 };
270270
271271 const siphash = SipHash64(2, 4);
......@@ -281,70 +281,70 @@ test "siphash64-2-4 sanity" {
281281
282282test "siphash128-2-4 sanity" {
283283 const vectors = [_][16]u8{
284 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
285 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
286 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
287 "\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51",
288 "\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79",
289 "\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27",
290 "\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e",
291 "\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39",
292 "\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4",
293 "\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed",
294 "\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba",
295 "\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18",
296 "\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25",
297 "\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7",
298 "\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02",
299 "\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9",
300 "\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77",
301 "\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40",
302 "\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23",
303 "\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1",
304 "\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb",
305 "\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12",
306 "\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae",
307 "\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c",
308 "\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad",
309 "\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f",
310 "\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66",
311 "\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94",
312 "\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4",
313 "\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7",
314 "\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87",
315 "\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35",
316 "\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68",
317 "\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf",
318 "\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde",
319 "\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8",
320 "\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11",
321 "\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b",
322 "\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5",
323 "\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9",
324 "\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8",
325 "\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb",
326 "\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b",
327 "\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89",
328 "\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42",
329 "\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c",
330 "\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02",
331 "\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b",
332 "\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16",
333 "\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03",
334 "\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f",
335 "\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38",
336 "\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c",
337 "\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e",
338 "\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87",
339 "\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda",
340 "\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36",
341 "\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e",
342 "\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d",
343 "\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59",
344 "\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40",
345 "\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a",
346 "\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd",
347 "\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c",
284 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93".*,
285 "\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45".*,
286 "\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4".*,
287 "\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51".*,
288 "\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79".*,
289 "\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27".*,
290 "\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e".*,
291 "\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39".*,
292 "\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4".*,
293 "\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed".*,
294 "\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba".*,
295 "\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18".*,
296 "\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25".*,
297 "\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7".*,
298 "\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02".*,
299 "\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9".*,
300 "\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77".*,
301 "\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40".*,
302 "\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23".*,
303 "\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1".*,
304 "\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb".*,
305 "\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12".*,
306 "\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae".*,
307 "\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c".*,
308 "\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad".*,
309 "\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f".*,
310 "\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66".*,
311 "\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94".*,
312 "\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4".*,
313 "\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7".*,
314 "\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87".*,
315 "\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35".*,
316 "\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68".*,
317 "\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf".*,
318 "\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde".*,
319 "\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8".*,
320 "\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11".*,
321 "\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b".*,
322 "\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5".*,
323 "\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9".*,
324 "\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8".*,
325 "\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb".*,
326 "\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b".*,
327 "\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89".*,
328 "\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42".*,
329 "\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c".*,
330 "\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02".*,
331 "\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b".*,
332 "\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16".*,
333 "\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03".*,
334 "\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f".*,
335 "\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38".*,
336 "\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c".*,
337 "\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e".*,
338 "\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87".*,
339 "\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda".*,
340 "\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36".*,
341 "\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e".*,
342 "\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d".*,
343 "\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59".*,
344 "\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40".*,
345 "\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a".*,
346 "\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd".*,
347 "\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c".*,
348348 };
349349
350350 const siphash = SipHash128(2, 4);
lib/std/io/test.zig+2-2
......@@ -595,8 +595,8 @@ test "Deserializer bad data" {
595595test "c out stream" {
596596 if (!builtin.link_libc) return error.SkipZigTest;
597597
598 const filename = c"tmp_io_test_file.txt";
599 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
598 const filename = "tmp_io_test_file.txt";
599 const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
600600 defer {
601601 _ = std.c.fclose(out_file);
602602 fs.deleteFileC(filename) catch {};
lib/std/mem.zig+13-11
......@@ -356,17 +356,17 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
356356 return true;
357357}
358358
359pub fn len(comptime T: type, ptr: [*]const T) usize {
359pub fn len(comptime T: type, ptr: [*:0]const T) usize {
360360 var count: usize = 0;
361361 while (ptr[count] != 0) : (count += 1) {}
362362 return count;
363363}
364364
365pub fn toSliceConst(comptime T: type, ptr: [*]const T) []const T {
365pub fn toSliceConst(comptime T: type, ptr: [*:0]const T) [:0]const T {
366366 return ptr[0..len(T, ptr)];
367367}
368368
369pub fn toSlice(comptime T: type, ptr: [*]T) []T {
369pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
370370 return ptr[0..len(T, ptr)];
371371}
372372
......@@ -1408,7 +1408,9 @@ test "toBytes" {
14081408fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
14091409 const size = @as(usize, @sizeOf(T));
14101410
1411 if (comptime !trait.is(builtin.TypeId.Pointer)(B) or meta.Child(B) != [size]u8) {
1411 if (comptime !trait.is(builtin.TypeId.Pointer)(B) or
1412 (meta.Child(B) != [size]u8 and meta.Child(B) != [size:0]u8))
1413 {
14121414 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));
14131415 }
14141416
......@@ -1430,12 +1432,12 @@ test "bytesAsValue" {
14301432 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
14311433 };
14321434
1433 testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
1435 testing.expect(deadbeef == bytesAsValue(u32, deadbeef_bytes).*);
14341436
1435 var codeface_bytes = switch (builtin.endian) {
1437 var codeface_bytes: [4]u8 = switch (builtin.endian) {
14361438 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
14371439 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
1438 };
1440 }.*;
14391441 var codeface = bytesAsValue(u32, &codeface_bytes);
14401442 testing.expect(codeface.* == 0xC0DEFACE);
14411443 codeface.* = 0;
......@@ -1456,14 +1458,14 @@ test "bytesAsValue" {
14561458 .d = 0xA1,
14571459 };
14581460 const inst_bytes = "\xBE\xEF\xDE\xA1";
1459 const inst2 = bytesAsValue(S, &inst_bytes);
1461 const inst2 = bytesAsValue(S, inst_bytes);
14601462 testing.expect(meta.eql(inst, inst2.*));
14611463}
14621464
14631465///Given a pointer to an array of bytes, returns a value of the specified type backed by a
14641466/// copy of those bytes.
14651467pub fn bytesToValue(comptime T: type, bytes: var) T {
1466 return bytesAsValue(T, &bytes).*;
1468 return bytesAsValue(T, bytes).*;
14671469}
14681470test "bytesToValue" {
14691471 const deadbeef_bytes = switch (builtin.endian) {
......@@ -1491,11 +1493,11 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
14911493}
14921494
14931495test "subArrayPtr" {
1494 const a1 = "abcdef";
1496 const a1: [6]u8 = "abcdef".*;
14951497 const sub1 = subArrayPtr(&a1, 2, 3);
14961498 testing.expect(eql(u8, sub1.*, "cde"));
14971499
1498 var a2 = "abcdef";
1500 var a2: [6]u8 = "abcdef".*;
14991501 var sub2 = subArrayPtr(&a2, 2, 3);
15001502
15011503 testing.expect(eql(u8, sub2, "cde"));
lib/std/meta.zig+6-6
......@@ -469,19 +469,19 @@ test "std.meta.eql" {
469469 const s_1 = S{
470470 .a = 134,
471471 .b = 123.3,
472 .c = "12345",
472 .c = "12345".*,
473473 };
474474
475475 const s_2 = S{
476476 .a = 1,
477477 .b = 123.3,
478 .c = "54321",
478 .c = "54321".*,
479479 };
480480
481481 const s_3 = S{
482482 .a = 134,
483483 .b = 123.3,
484 .c = "12345",
484 .c = "12345".*,
485485 };
486486
487487 const u_1 = U{ .f = 24 };
......@@ -494,9 +494,9 @@ test "std.meta.eql" {
494494 testing.expect(eql(u_1, u_3));
495495 testing.expect(!eql(u_1, u_2));
496496
497 var a1 = "abcdef";
498 var a2 = "abcdef";
499 var a3 = "ghijkl";
497 var a1 = "abcdef".*;
498 var a2 = "abcdef".*;
499 var a3 = "ghijkl".*;
500500
501501 testing.expect(eql(a1, a2));
502502 testing.expect(!eql(a1, a3));
lib/std/meta/trait.zig-2
......@@ -319,7 +319,6 @@ test "std.meta.trait.isNumber" {
319319 testing.expect(!isNumber(NotANumber));
320320}
321321
322///
323322pub fn isConstPtr(comptime T: type) bool {
324323 if (!comptime is(builtin.TypeId.Pointer)(T)) return false;
325324 const info = @typeInfo(T);
......@@ -335,7 +334,6 @@ test "std.meta.trait.isConstPtr" {
335334 testing.expect(!isConstPtr(@typeOf(6)));
336335}
337336
338///
339337pub fn isContainer(comptime T: type) bool {
340338 const info = @typeInfo(T);
341339 return switch (info) {
lib/std/net.zig+10-10
......@@ -360,7 +360,7 @@ pub const Address = extern union {
360360 unreachable;
361361 }
362362
363 const path_len = std.mem.len(u8, &self.un.path);
363 const path_len = std.mem.len(u8, @ptrCast([*:0]const u8, &self.un.path));
364364 return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len);
365365 },
366366 else => unreachable,
......@@ -666,35 +666,35 @@ const Policy = struct {
666666
667667const defined_policies = [_]Policy{
668668 Policy{
669 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
669 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".*,
670670 .len = 15,
671671 .mask = 0xff,
672672 .prec = 50,
673673 .label = 0,
674674 },
675675 Policy{
676 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00",
676 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00".*,
677677 .len = 11,
678678 .mask = 0xff,
679679 .prec = 35,
680680 .label = 4,
681681 },
682682 Policy{
683 .addr = "\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
683 .addr = "\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
684684 .len = 1,
685685 .mask = 0xff,
686686 .prec = 30,
687687 .label = 2,
688688 },
689689 Policy{
690 .addr = "\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
690 .addr = "\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
691691 .len = 3,
692692 .mask = 0xff,
693693 .prec = 5,
694694 .label = 5,
695695 },
696696 Policy{
697 .addr = "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
697 .addr = "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
698698 .len = 0,
699699 .mask = 0xfe,
700700 .prec = 3,
......@@ -708,7 +708,7 @@ const defined_policies = [_]Policy{
708708 // { "\x3f\xfe", 1, 0xff, 1, 12 },
709709 // Last rule must match all addresses to stop loop.
710710 Policy{
711 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
711 .addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
712712 .len = 0,
713713 .mask = 0,
714714 .prec = 40,
......@@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(
812812 family: os.sa_family_t,
813813 port: u16,
814814) !void {
815 const file = fs.File.openReadC(c"/etc/hosts") catch |err| switch (err) {
815 const file = fs.File.openReadC("/etc/hosts") catch |err| switch (err) {
816816 error.FileNotFound,
817817 error.NotDir,
818818 error.AccessDenied,
......@@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
10061006 };
10071007 errdefer rc.deinit();
10081008
1009 const file = fs.File.openReadC(c"/etc/resolv.conf") catch |err| switch (err) {
1009 const file = fs.File.openReadC("/etc/resolv.conf") catch |err| switch (err) {
10101010 error.FileNotFound,
10111011 error.NotDir,
10121012 error.AccessDenied,
......@@ -1271,7 +1271,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
12711271 var tmp: [256]u8 = undefined;
12721272 // Returns len of compressed name. strlen to get canon name.
12731273 _ = try os.dn_expand(packet, data, &tmp);
1274 const canon_name = mem.toSliceConst(u8, &tmp);
1274 const canon_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &tmp));
12751275 if (isValidHostName(canon_name)) {
12761276 try ctx.canon.replaceContents(canon_name);
12771277 }
lib/std/os.zig+52-47
......@@ -66,12 +66,12 @@ pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {
6666pub usingnamespace @import("os/bits.zig");
6767
6868/// See also `getenv`. Populated by startup code before main().
69pub var environ: [][*]u8 = undefined;
69pub var environ: [][*:0]u8 = undefined;
7070
7171/// Populated by startup code before main().
7272/// Not available on Windows. See `std.process.args`
7373/// for obtaining the process arguments.
74pub var argv: [][*]u8 = undefined;
74pub var argv: [][*:0]u8 = undefined;
7575
7676/// To obtain errno, call this function with the return value of the
7777/// system function call. For some systems this will obtain the value directly
......@@ -157,7 +157,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
157157}
158158
159159fn getRandomBytesDevURandom(buf: []u8) !void {
160 const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
160 const fd = try openC("/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
161161 defer close(fd);
162162
163163 const st = try fstat(fd);
......@@ -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: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]const ?[*]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: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]c
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 => {},
......@@ -820,8 +820,8 @@ pub fn execvpe(
820820 argv_slice: []const []const u8,
821821 env_map: *const std.BufMap,
822822) (ExecveError || error{OutOfMemory}) {
823 const argv_buf = try allocator.alloc(?[*]u8, argv_slice.len + 1);
824 mem.set(?[*]u8, argv_buf, null);
823 const argv_buf = try allocator.alloc(?[*:0]u8, argv_slice.len + 1);
824 mem.set(?[*:0]u8, argv_buf, null);
825825 defer {
826826 for (argv_buf) |arg| {
827827 const arg_buf = if (arg) |ptr| mem.toSlice(u8, ptr) else break;
......@@ -834,20 +834,24 @@ pub fn execvpe(
834834 @memcpy(arg_buf.ptr, arg.ptr, arg.len);
835835 arg_buf[arg.len] = 0;
836836
837 argv_buf[i] = arg_buf.ptr;
837 // TODO avoid @ptrCast using slice syntax with https://github.com/ziglang/zig/issues/3731
838 argv_buf[i] = @ptrCast([*:0]u8, arg_buf.ptr);
838839 }
839840 argv_buf[argv_slice.len] = null;
840841
841842 const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);
842843 defer freeNullDelimitedEnvMap(allocator, envp_buf);
843844
844 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);
845849}
846850
847pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![]?[*]u8 {
851pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![:null]?[*:0]u8 {
848852 const envp_count = env_map.count();
849 const envp_buf = try allocator.alloc(?[*]u8, envp_count + 1);
850 mem.set(?[*]u8, envp_buf, null);
853 const envp_buf = try allocator.alloc(?[*:0]u8, envp_count + 1);
854 mem.set(?[*:0]u8, envp_buf, null);
851855 errdefer freeNullDelimitedEnvMap(allocator, envp_buf);
852856 {
853857 var it = env_map.iterator();
......@@ -859,15 +863,17 @@ pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.
859863 @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);
860864 env_buf[env_buf.len - 1] = 0;
861865
862 envp_buf[i] = env_buf.ptr;
866 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
867 envp_buf[i] = @ptrCast([*:0]u8, env_buf.ptr);
863868 }
864869 assert(i == envp_count);
865870 }
871 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
866872 assert(envp_buf[envp_count] == null);
867 return envp_buf;
873 return @ptrCast([*:null]?[*:0]u8, envp_buf.ptr)[0..envp_count];
868874}
869875
870pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*]u8) void {
876pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) void {
871877 for (envp_buf) |env| {
872878 const env_buf = if (env) |ptr| ptr[0 .. mem.len(u8, ptr) + 1] else break;
873879 allocator.free(env_buf);
......@@ -896,8 +902,7 @@ pub fn getenv(key: []const u8) ?[]const u8 {
896902
897903/// Get an environment variable with a null-terminated name.
898904/// See also `getenv`.
899/// TODO https://github.com/ziglang/zig/issues/265
900pub fn getenvC(key: [*]const u8) ?[]const u8 {
905pub fn getenvC(key: [*:0]const u8) ?[]const u8 {
901906 if (builtin.link_libc) {
902907 const value = system.getenv(key) orelse return null;
903908 return mem.toSliceConst(u8, value);
......@@ -922,7 +927,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
922927 break :blk errno(system.getcwd(out_buffer.ptr, out_buffer.len));
923928 };
924929 switch (err) {
925 0 => return mem.toSlice(u8, out_buffer.ptr),
930 0 => return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer.ptr)),
926931 EFAULT => unreachable,
927932 EINVAL => unreachable,
928933 ENOENT => return error.CurrentWorkingDirectoryUnlinked,
......@@ -966,7 +971,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
966971
967972/// This is the same as `symlink` except the parameters are null-terminated pointers.
968973/// See also `symlink`.
969pub 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 {
970975 if (builtin.os == .windows) {
971976 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
972977 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);
......@@ -998,7 +1003,7 @@ pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const
9981003 return symlinkatC(target_path_c, newdirfd, sym_link_path_c);
9991004}
10001005
1001pub 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 {
10021007 switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) {
10031008 0 => return,
10041009 EFAULT => unreachable,
......@@ -1052,7 +1057,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {
10521057}
10531058
10541059/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.
1055pub fn unlinkC(file_path: [*]const u8) UnlinkError!void {
1060pub fn unlinkC(file_path: [*:0]const u8) UnlinkError!void {
10561061 if (builtin.os == .windows) {
10571062 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
10581063 return windows.DeleteFileW(&file_path_w);
......@@ -1092,7 +1097,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo
10921097}
10931098
10941099/// Same as `unlinkat` but `file_path` is a null-terminated string.
1095pub 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 {
10961101 if (builtin.os == .windows) {
10971102 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
10981103 return unlinkatW(dirfd, &file_path_w, flags);
......@@ -1121,7 +1126,7 @@ pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatErro
11211126}
11221127
11231128/// Same as `unlinkat` but `sub_path_w` is UTF16LE, NT prefixed. Windows only.
1124pub 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 {
11251130 const w = windows;
11261131
11271132 const want_rmdir_behavior = (flags & AT_REMOVEDIR) != 0;
......@@ -1216,7 +1221,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
12161221}
12171222
12181223/// Same as `rename` except the parameters are null-terminated byte arrays.
1219pub 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 {
12201225 if (builtin.os == .windows) {
12211226 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
12221227 const new_path_w = try windows.cStrToPrefixedFileW(new_path);
......@@ -1248,7 +1253,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
12481253
12491254/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
12501255/// Assumes target is Windows.
1251pub 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 {
12521257 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
12531258 return windows.MoveFileExW(old_path, new_path, flags);
12541259}
......@@ -1282,7 +1287,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
12821287}
12831288
12841289/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.
1285pub fn mkdirC(dir_path: [*]const u8, mode: u32) MakeDirError!void {
1290pub fn mkdirC(dir_path: [*:0]const u8, mode: u32) MakeDirError!void {
12861291 if (builtin.os == .windows) {
12871292 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
12881293 return windows.CreateDirectoryW(&dir_path_w, null);
......@@ -1332,7 +1337,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
13321337}
13331338
13341339/// Same as `rmdir` except the parameter is null-terminated.
1335pub fn rmdirC(dir_path: [*]const u8) DeleteDirError!void {
1340pub fn rmdirC(dir_path: [*:0]const u8) DeleteDirError!void {
13361341 if (builtin.os == .windows) {
13371342 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
13381343 return windows.RemoveDirectoryW(&dir_path_w);
......@@ -1379,7 +1384,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
13791384}
13801385
13811386/// Same as `chdir` except the parameter is null-terminated.
1382pub fn chdirC(dir_path: [*]const u8) ChangeCurDirError!void {
1387pub fn chdirC(dir_path: [*:0]const u8) ChangeCurDirError!void {
13831388 if (builtin.os == .windows) {
13841389 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
13851390 @compileError("TODO implement chdir for Windows");
......@@ -1421,7 +1426,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
14211426}
14221427
14231428/// Same as `readlink` except `file_path` is null-terminated.
1424pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1429pub fn readlinkC(file_path: [*:0]const u8, out_buffer: []u8) ReadLinkError![]u8 {
14251430 if (builtin.os == .windows) {
14261431 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
14271432 @compileError("TODO implement readlink for Windows");
......@@ -1442,7 +1447,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
14421447 }
14431448}
14441449
1445pub 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 {
14461451 if (builtin.os == .windows) {
14471452 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
14481453 @compileError("TODO implement readlink for Windows");
......@@ -2129,7 +2134,7 @@ pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INoti
21292134}
21302135
21312136/// Same as `inotify_add_watch` except pathname is null-terminated.
2132pub 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 {
21332138 const rc = system.inotify_add_watch(inotify_fd, pathname, mask);
21342139 switch (errno(rc)) {
21352140 0 => return @intCast(i32, rc),
......@@ -2286,7 +2291,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
22862291}
22872292
22882293/// Same as `access` except `path` is null-terminated.
2289pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
2294pub fn accessC(path: [*:0]const u8, mode: u32) AccessError!void {
22902295 if (builtin.os == .windows) {
22912296 const path_w = try windows.cStrToPrefixedFileW(path);
22922297 _ = try windows.GetFileAttributesW(&path_w);
......@@ -2313,7 +2318,7 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
23132318/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
23142319/// Otherwise use `access` or `accessC`.
23152320/// TODO currently this ignores `mode`.
2316pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!void {
2321pub fn accessW(path: [*:0]const u16, mode: u32) windows.GetFileAttributesError!void {
23172322 const ret = try windows.GetFileAttributesW(path);
23182323 if (ret != windows.INVALID_FILE_ATTRIBUTES) {
23192324 return;
......@@ -2380,7 +2385,7 @@ pub fn sysctl(
23802385}
23812386
23822387pub fn sysctlbynameC(
2383 name: [*]const u8,
2388 name: [*:0]const u8,
23842389 oldp: ?*c_void,
23852390 oldlenp: ?*usize,
23862391 newp: ?*c_void,
......@@ -2562,7 +2567,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE
25622567}
25632568
25642569/// Same as `realpath` except `pathname` is null-terminated.
2565pub 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 {
25662571 if (builtin.os == .windows) {
25672572 const pathname_w = try windows.cStrToPrefixedFileW(pathname);
25682573 return realpathW(&pathname_w, out_buffer);
......@@ -2571,10 +2576,10 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
25712576 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);
25722577 defer close(fd);
25732578
2574 var procfs_buf: ["/proc/self/fd/-2147483648\x00".len]u8 = undefined;
2579 var procfs_buf: ["/proc/self/fd/-2147483648".len:0]u8 = undefined;
25752580 const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;
25762581
2577 return readlinkC(proc_path.ptr, out_buffer);
2582 return readlinkC(@ptrCast([*:0]const u8, proc_path.ptr), out_buffer);
25782583 }
25792584 const result_path = std.c.realpath(pathname, out_buffer) orelse switch (std.c._errno().*) {
25802585 EINVAL => unreachable,
......@@ -2593,7 +2598,7 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
25932598}
25942599
25952600/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.
2596pub 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 {
25972602 const h_file = try windows.CreateFileW(
25982603 pathname,
25992604 windows.GENERIC_READ,
......@@ -2674,7 +2679,7 @@ pub fn dl_iterate_phdr(
26742679 if (it.end()) {
26752680 var info = dl_phdr_info{
26762681 .dlpi_addr = elf_base,
2677 .dlpi_name = c"/proc/self/exe",
2682 .dlpi_name = "/proc/self/exe",
26782683 .dlpi_phdr = phdrs.ptr,
26792684 .dlpi_phnum = ehdr.e_phnum,
26802685 };
......@@ -2748,8 +2753,8 @@ pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
27482753
27492754/// Used to convert a slice to a null terminated slice on the stack.
27502755/// TODO https://github.com/ziglang/zig/issues/287
2751pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {
2752 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;
27532758 // >= rather than > to make room for the null byte
27542759 if (file_path.len >= PATH_MAX) return error.NameTooLong;
27552760 mem.copy(u8, &path_with_null, file_path);
......@@ -2854,7 +2859,7 @@ pub const GetHostNameError = error{PermissionDenied} || UnexpectedError;
28542859pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
28552860 if (builtin.link_libc) {
28562861 switch (errno(system.gethostname(name_buffer, name_buffer.len))) {
2857 0 => return mem.toSlice(u8, name_buffer),
2862 0 => return mem.toSlice(u8, @ptrCast([*:0]u8, name_buffer)),
28582863 EFAULT => unreachable,
28592864 ENAMETOOLONG => unreachable, // HOST_NAME_MAX prevents this
28602865 EPERM => return error.PermissionDenied,
......@@ -2865,7 +2870,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
28652870 var uts: utsname = undefined;
28662871 switch (errno(system.uname(&uts))) {
28672872 0 => {
2868 const hostname = mem.toSlice(u8, &uts.nodename);
2873 const hostname = mem.toSlice(u8, @ptrCast([*:0]u8, &uts.nodename));
28692874 mem.copy(u8, name_buffer, hostname);
28702875 return name_buffer[0..hostname.len];
28712876 },
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
......@@ -1363,7 +1363,7 @@ pub const addrinfo = extern struct {
13631363 protocol: i32,
13641364 addrlen: socklen_t,
13651365 addr: ?*sockaddr,
1366 canonname: ?[*]u8,
1366 canonname: ?[*:0]u8,
13671367 next: ?*addrinfo,
13681368};
13691369
lib/std/os/linux.zig+1-1
......@@ -1053,7 +1053,7 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf
10531053 if (it.end()) {
10541054 var info = dl_phdr_info{
10551055 .dlpi_addr = elf_base,
1056 .dlpi_name = c"/proc/self/exe",
1056 .dlpi_name = "/proc/self/exe",
10571057 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
10581058 .dlpi_phnum = __ehdr_start.e_phnum,
10591059 };
lib/std/os/linux/test.zig+2-2
......@@ -56,7 +56,7 @@ test "statx" {
5656 }
5757
5858 var statx_buf: linux.Statx = undefined;
59 switch (linux.getErrno(linux.statx(file.handle, c"", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
59 switch (linux.getErrno(linux.statx(file.handle, "", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
6060 0 => {},
6161 // The statx syscall was only introduced in linux 4.11
6262 linux.ENOSYS => return error.SkipZigTest,
......@@ -64,7 +64,7 @@ test "statx" {
6464 }
6565
6666 var stat_buf: linux.Stat = undefined;
67 switch (linux.getErrno(linux.fstatat(file.handle, c"", &stat_buf, linux.AT_EMPTY_PATH))) {
67 switch (linux.getErrno(linux.fstatat(file.handle, "", &stat_buf, linux.AT_EMPTY_PATH))) {
6868 0 => {},
6969 else => unreachable,
7070 }
lib/std/os/linux/vdso.zig+4-2
......@@ -65,7 +65,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
6565 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue;
6666 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue;
6767 if (0 == syms[i].st_shndx) continue;
68 if (!mem.eql(u8, name, mem.toSliceConst(u8, strings + syms[i].st_name))) continue;
68 const sym_name = @ptrCast([*:0]const u8, strings + syms[i].st_name);
69 if (!mem.eql(u8, name, mem.toSliceConst(u8, sym_name))) continue;
6970 if (maybe_versym) |versym| {
7071 if (!checkver(maybe_verdef.?, versym[i], vername, strings))
7172 continue;
......@@ -87,5 +88,6 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
8788 def = @intToPtr(*elf.Verdef, @ptrToInt(def) + def.vd_next);
8889 }
8990 const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);
90 return mem.eql(u8, vername, mem.toSliceConst(u8, strings + aux.vda_name));
91 const vda_name = @ptrCast([*:0]const u8, strings + aux.vda_name);
92 return mem.eql(u8, vername, mem.toSliceConst(u8, vda_name));
9193}
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+9-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.
......@@ -968,6 +968,7 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
968968 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
969969 if (end_index + suffix.len > result.len) return error.NameTooLong;
970970 mem.copy(u16, result[end_index..], suffix);
971 result[end_index + suffix.len] = 0;
971972 return result;
972973}
973974
lib/std/process.zig+10-10
......@@ -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);
......@@ -473,14 +473,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
473473}
474474
475475test "windows arg parsing" {
476 testWindowsCmdLine(c"a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
477 testWindowsCmdLine(c"\"abc\" d e", [_][]const u8{ "abc", "d", "e" });
478 testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [_][]const u8{ "a\\\\\\b", "de fg", "h" });
479 testWindowsCmdLine(c"a\\\\\\\"b c d", [_][]const u8{ "a\\\"b", "c", "d" });
480 testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [_][]const u8{ "a\\\\b c", "d", "e" });
481 testWindowsCmdLine(c"a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
482
483 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
476 testWindowsCmdLine("a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
477 testWindowsCmdLine("\"abc\" d e", [_][]const u8{ "abc", "d", "e" });
478 testWindowsCmdLine("a\\\\\\b d\"e f\"g h", [_][]const u8{ "a\\\\\\b", "de fg", "h" });
479 testWindowsCmdLine("a\\\\\\\"b c d", [_][]const u8{ "a\\\"b", "c", "d" });
480 testWindowsCmdLine("a\\\\\\\\\"b c\" d e", [_][]const u8{ "a\\\\b c", "d", "e" });
481 testWindowsCmdLine("a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
482
483 testWindowsCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
484484 ".\\..\\zig-cache\\build",
485485 "bin\\zig.exe",
486486 ".\\..",
lib/std/special/c.zig+5-5
......@@ -66,14 +66,14 @@ extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {
6666}
6767
6868extern fn strerror(errnum: c_int) [*]const u8 {
69 return c"TODO strerror implementation";
69 return "TODO strerror implementation";
7070}
7171
7272test "strncmp" {
73 std.testing.expect(strncmp(c"a", c"b", 1) == -1);
74 std.testing.expect(strncmp(c"a", c"c", 1) == -2);
75 std.testing.expect(strncmp(c"b", c"a", 1) == 1);
76 std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253);
73 std.testing.expect(strncmp("a", "b", 1) == -1);
74 std.testing.expect(strncmp("a", "c", 1) == -2);
75 std.testing.expect(strncmp("b", "a", 1) == 1);
76 std.testing.expect(strncmp("\xff", "\x02", 1) == 253);
7777}
7878
7979// Avoid dragging in the runtime safety mechanisms into this .o file,
lib/std/special/start.zig+6-6
......@@ -123,12 +123,12 @@ fn posixCallMainAndExit() noreturn {
123123 @setAlignStack(16);
124124 }
125125 const argc = starting_stack_ptr[0];
126 const argv = @ptrCast([*][*]u8, starting_stack_ptr + 1);
126 const argv = @ptrCast([*][*:0]u8, starting_stack_ptr + 1);
127127
128 const envp_optional = @ptrCast([*]?[*]u8, argv + argc + 1);
128 const envp_optional = @ptrCast([*:null]?[*:0]u8, argv + argc + 1);
129129 var envp_count: usize = 0;
130130 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}
131 const envp = @ptrCast([*][*]u8, envp_optional)[0..envp_count];
131 const envp = @ptrCast([*][*:0]u8, envp_optional)[0..envp_count];
132132
133133 if (builtin.os == .linux) {
134134 // Find the beginning of the auxiliary vector
......@@ -168,7 +168,7 @@ fn posixCallMainAndExit() noreturn {
168168 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));
169169}
170170
171fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
171fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
172172 std.os.argv = argv[0..argc];
173173 std.os.environ = envp;
174174
......@@ -177,10 +177,10 @@ fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
177177 return initEventLoopAndCallMain();
178178}
179179
180extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
180extern fn main(c_argc: i32, c_argv: [*][*:0]u8, c_envp: [*:null]?[*:0]u8) i32 {
181181 var env_count: usize = 0;
182182 while (c_envp[env_count] != null) : (env_count += 1) {}
183 const envp = @ptrCast([*][*]u8, c_envp)[0..env_count];
183 const envp = @ptrCast([*][*:0]u8, c_envp)[0..env_count];
184184 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);
185185}
186186
lib/std/special/test_runner.zig+1-1
......@@ -36,7 +36,7 @@ pub fn main() anyerror!void {
3636 }
3737 root_node.end();
3838 if (ok_count == test_fn_list.len) {
39 std.debug.warn("All tests passed.\n");
39 std.debug.warn("All {} tests passed.\n", ok_count);
4040 } else {
4141 std.debug.warn("{} passed; {} skipped.\n", ok_count, skip_count);
4242 }
lib/std/thread.zig+1-1
......@@ -353,7 +353,7 @@ pub const Thread = struct {
353353 }
354354 var count: c_int = undefined;
355355 var count_len: usize = @sizeOf(c_int);
356 const name = if (comptime std.Target.current.isDarwin()) c"hw.logicalcpu" else c"hw.ncpu";
356 const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu";
357357 os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {
358358 error.NameTooLong => unreachable,
359359 else => |e| return e,
lib/std/valgrind/memcheck.zig+1-1
......@@ -3,7 +3,7 @@ const testing = std.testing;
33const valgrind = std.valgrind;
44
55pub const MemCheckClientRequest = extern enum {
6 MakeMemNoAccess = valgrind.ToolBase("MC"),
6 MakeMemNoAccess = valgrind.ToolBase("MC".*),
77 MakeMemUndefined,
88 MakeMemDefined,
99 Discard,
lib/std/zig/ast.zig+23-8
......@@ -1531,14 +1531,14 @@ pub const Node = struct {
15311531 };
15321532
15331533 pub const PrefixOp = struct {
1534 base: Node,
1534 base: Node = Node{ .id = .PrefixOp },
15351535 op_token: TokenIndex,
15361536 op: Op,
15371537 rhs: *Node,
15381538
15391539 pub const Op = union(enum) {
15401540 AddressOf,
1541 ArrayType: *Node,
1541 ArrayType: ArrayInfo,
15421542 Await,
15431543 BitNot,
15441544 BoolNot,
......@@ -1552,11 +1552,17 @@ pub const Node = struct {
15521552 Try,
15531553 };
15541554
1555 pub const ArrayInfo = struct {
1556 len_expr: *Node,
1557 sentinel: ?*Node,
1558 };
1559
15551560 pub const PtrInfo = struct {
1556 allowzero_token: ?TokenIndex,
1557 align_info: ?Align,
1558 const_token: ?TokenIndex,
1559 volatile_token: ?TokenIndex,
1561 allowzero_token: ?TokenIndex = null,
1562 align_info: ?Align = null,
1563 const_token: ?TokenIndex = null,
1564 volatile_token: ?TokenIndex = null,
1565 sentinel: ?*Node = null,
15601566
15611567 pub const Align = struct {
15621568 node: *Node,
......@@ -1575,6 +1581,11 @@ pub const Node = struct {
15751581 switch (self.op) {
15761582 // TODO https://github.com/ziglang/zig/issues/1107
15771583 Op.SliceType => |addr_of_info| {
1584 if (addr_of_info.sentinel) |sentinel| {
1585 if (i < 1) return sentinel;
1586 i -= 1;
1587 }
1588
15781589 if (addr_of_info.align_info) |align_info| {
15791590 if (i < 1) return align_info.node;
15801591 i -= 1;
......@@ -1588,9 +1599,13 @@ pub const Node = struct {
15881599 }
15891600 },
15901601
1591 Op.ArrayType => |size_expr| {
1592 if (i < 1) return size_expr;
1602 Op.ArrayType => |array_info| {
1603 if (i < 1) return array_info.len_expr;
15931604 i -= 1;
1605 if (array_info.sentinel) |sentinel| {
1606 if (i < 1) return sentinel;
1607 i -= 1;
1608 }
15941609 },
15951610
15961611 Op.AddressOf,
lib/std/zig/parse.zig+139-98
......@@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
10851085 const node = try arena.create(Node.SuffixOp);
10861086 node.* = Node.SuffixOp{
10871087 .base = Node{ .id = .SuffixOp },
1088 .lhs = .{.node = undefined}, // set by caller
1088 .lhs = .{ .node = undefined }, // set by caller
10891089 .op = op,
10901090 .rtoken = try expectToken(it, tree, .RBrace),
10911091 };
......@@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11381138
11391139 while (try parseSuffixOp(arena, it, tree)) |node| {
11401140 switch (node.id) {
1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
11421142 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
11431143 else => unreachable,
11441144 }
......@@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11541154 const node = try arena.create(Node.SuffixOp);
11551155 node.* = Node.SuffixOp{
11561156 .base = Node{ .id = .SuffixOp },
1157 .lhs = .{.node = res},
1157 .lhs = .{ .node = res },
11581158 .op = Node.SuffixOp.Op{
11591159 .Call = Node.SuffixOp.Op.Call{
11601160 .params = params.list,
......@@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11711171 while (true) {
11721172 if (try parseSuffixOp(arena, it, tree)) |node| {
11731173 switch (node.id) {
1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},
1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
11751175 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
11761176 else => unreachable,
11771177 }
......@@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11821182 const call = try arena.create(Node.SuffixOp);
11831183 call.* = Node.SuffixOp{
11841184 .base = Node{ .id = .SuffixOp },
1185 .lhs = .{.node = res},
1185 .lhs = .{ .node = res },
11861186 .op = Node.SuffixOp.Op{
11871187 .Call = Node.SuffixOp.Op.Call{
11881188 .params = params.list,
......@@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
15311531
15321532 // anon container literal
15331533 if (try parseInitList(arena, it, tree)) |node| {
1534 node.lhs = .{.dot = dot};
1534 node.lhs = .{ .dot = dot };
15351535 return &node.base;
15361536 }
15371537
......@@ -2246,63 +2246,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
22462246 return &node.base;
22472247 }
22482248
2249 if (try parseArrayTypeStart(arena, it, tree)) |node| {
2250 switch (node.cast(Node.PrefixOp).?.op) {
2251 .ArrayType => {},
2252 .SliceType => |*slice_type| {
2253 // Collect pointer qualifiers in any order, but disallow duplicates
2254 while (true) {
2255 if (try parseByteAlign(arena, it, tree)) |align_expr| {
2256 if (slice_type.align_info != null) {
2257 try tree.errors.push(AstError{
2258 .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index },
2259 });
2260 return error.ParseError;
2261 }
2262 slice_type.align_info = Node.PrefixOp.PtrInfo.Align{
2263 .node = align_expr,
2264 .bit_range = null,
2265 };
2266 continue;
2267 }
2268 if (eatToken(it, .Keyword_const)) |const_token| {
2269 if (slice_type.const_token != null) {
2270 try tree.errors.push(AstError{
2271 .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index },
2272 });
2273 return error.ParseError;
2274 }
2275 slice_type.const_token = const_token;
2276 continue;
2277 }
2278 if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2279 if (slice_type.volatile_token != null) {
2280 try tree.errors.push(AstError{
2281 .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index },
2282 });
2283 return error.ParseError;
2284 }
2285 slice_type.volatile_token = volatile_token;
2286 continue;
2287 }
2288 if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {
2289 if (slice_type.allowzero_token != null) {
2290 try tree.errors.push(AstError{
2291 .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index },
2292 });
2293 return error.ParseError;
2294 }
2295 slice_type.allowzero_token = allowzero_token;
2296 continue;
2297 }
2298 break;
2299 }
2300 },
2301 else => unreachable,
2302 }
2303 return node;
2304 }
2305
23062249 if (try parsePtrTypeStart(arena, it, tree)) |node| {
23072250 // If the token encountered was **, there will be two nodes instead of one.
23082251 // The attributes should be applied to the rightmost operator.
......@@ -2361,6 +2304,63 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
23612304 return node;
23622305 }
23632306
2307 if (try parseArrayTypeStart(arena, it, tree)) |node| {
2308 switch (node.cast(Node.PrefixOp).?.op) {
2309 .ArrayType => {},
2310 .SliceType => |*slice_type| {
2311 // Collect pointer qualifiers in any order, but disallow duplicates
2312 while (true) {
2313 if (try parseByteAlign(arena, it, tree)) |align_expr| {
2314 if (slice_type.align_info != null) {
2315 try tree.errors.push(AstError{
2316 .ExtraAlignQualifier = AstError.ExtraAlignQualifier{ .token = it.index },
2317 });
2318 return error.ParseError;
2319 }
2320 slice_type.align_info = Node.PrefixOp.PtrInfo.Align{
2321 .node = align_expr,
2322 .bit_range = null,
2323 };
2324 continue;
2325 }
2326 if (eatToken(it, .Keyword_const)) |const_token| {
2327 if (slice_type.const_token != null) {
2328 try tree.errors.push(AstError{
2329 .ExtraConstQualifier = AstError.ExtraConstQualifier{ .token = it.index },
2330 });
2331 return error.ParseError;
2332 }
2333 slice_type.const_token = const_token;
2334 continue;
2335 }
2336 if (eatToken(it, .Keyword_volatile)) |volatile_token| {
2337 if (slice_type.volatile_token != null) {
2338 try tree.errors.push(AstError{
2339 .ExtraVolatileQualifier = AstError.ExtraVolatileQualifier{ .token = it.index },
2340 });
2341 return error.ParseError;
2342 }
2343 slice_type.volatile_token = volatile_token;
2344 continue;
2345 }
2346 if (eatToken(it, .Keyword_allowzero)) |allowzero_token| {
2347 if (slice_type.allowzero_token != null) {
2348 try tree.errors.push(AstError{
2349 .ExtraAllowZeroQualifier = AstError.ExtraAllowZeroQualifier{ .token = it.index },
2350 });
2351 return error.ParseError;
2352 }
2353 slice_type.allowzero_token = allowzero_token;
2354 continue;
2355 }
2356 break;
2357 }
2358 },
2359 else => unreachable,
2360 }
2361 return node;
2362 }
2363
23642364 return null;
23652365}
23662366
......@@ -2459,10 +2459,21 @@ const AnnotatedParamList = struct {
24592459fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
24602460 const lbracket = eatToken(it, .LBracket) orelse return null;
24612461 const expr = try parseExpr(arena, it, tree);
2462 const sentinel = if (eatToken(it, .Colon)) |_|
2463 try expectNode(arena, it, tree, parseExpr, AstError{
2464 .ExpectedExpr = .{ .token = it.index },
2465 })
2466 else
2467 null;
24622468 const rbracket = try expectToken(it, tree, .RBracket);
24632469
2464 const op = if (expr) |element_type|
2465 Node.PrefixOp.Op{ .ArrayType = element_type }
2470 const op = if (expr) |len_expr|
2471 Node.PrefixOp.Op{
2472 .ArrayType = .{
2473 .len_expr = len_expr,
2474 .sentinel = sentinel,
2475 },
2476 }
24662477 else
24672478 Node.PrefixOp.Op{
24682479 .SliceType = Node.PrefixOp.PtrInfo{
......@@ -2470,6 +2481,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
24702481 .align_info = null,
24712482 .const_token = null,
24722483 .volatile_token = null,
2484 .sentinel = sentinel,
24732485 },
24742486 };
24752487
......@@ -2489,47 +2501,76 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
24892501/// / PTRUNKNOWN
24902502/// / PTRC
24912503fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2492 const token = eatAnnotatedToken(it, .Asterisk) orelse
2493 eatAnnotatedToken(it, .AsteriskAsterisk) orelse
2494 eatAnnotatedToken(it, .BracketStarBracket) orelse
2495 eatAnnotatedToken(it, .BracketStarCBracket) orelse
2496 return null;
2504 if (eatToken(it, .Asterisk)) |asterisk| {
2505 const sentinel = if (eatToken(it, .Colon)) |_|
2506 try expectNode(arena, it, tree, parseExpr, AstError{
2507 .ExpectedExpr = .{ .token = it.index },
2508 })
2509 else
2510 null;
2511 const node = try arena.create(Node.PrefixOp);
2512 node.* = .{
2513 .op_token = asterisk,
2514 .op = .{ .PtrType = .{ .sentinel = sentinel } },
2515 .rhs = undefined, // set by caller
2516 };
2517 return &node.base;
2518 }
24972519
2498 const node = try arena.create(Node.PrefixOp);
2499 node.* = Node.PrefixOp{
2500 .base = Node{ .id = .PrefixOp },
2501 .op_token = token.index,
2502 .op = Node.PrefixOp.Op{
2503 .PtrType = Node.PrefixOp.PtrInfo{
2504 .allowzero_token = null,
2505 .align_info = null,
2506 .const_token = null,
2507 .volatile_token = null,
2508 },
2509 },
2510 .rhs = undefined, // set by caller
2511 };
2520 if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| {
2521 const node = try arena.create(Node.PrefixOp);
2522 node.* = Node.PrefixOp{
2523 .op_token = double_asterisk,
2524 .op = Node.PrefixOp.Op{ .PtrType = .{} },
2525 .rhs = undefined, // set by caller
2526 };
25122527
2513 // Special case for **, which is its own token
2514 if (token.ptr.id == .AsteriskAsterisk) {
2528 // Special case for **, which is its own token
25152529 const child = try arena.create(Node.PrefixOp);
25162530 child.* = Node.PrefixOp{
2517 .base = Node{ .id = .PrefixOp },
2518 .op_token = token.index,
2519 .op = Node.PrefixOp.Op{
2520 .PtrType = Node.PrefixOp.PtrInfo{
2521 .allowzero_token = null,
2522 .align_info = null,
2523 .const_token = null,
2524 .volatile_token = null,
2525 },
2526 },
2531 .op_token = double_asterisk,
2532 .op = Node.PrefixOp.Op{ .PtrType = .{} },
25272533 .rhs = undefined, // set by caller
25282534 };
25292535 node.rhs = &child.base;
2530 }
25312536
2532 return &node.base;
2537 return &node.base;
2538 }
2539 if (eatToken(it, .LBracket)) |lbracket| {
2540 const asterisk = eatToken(it, .Asterisk) orelse {
2541 putBackToken(it, lbracket);
2542 return null;
2543 };
2544 if (eatToken(it, .Identifier)) |ident| {
2545 if (!std.mem.eql(u8, tree.tokenSlice(ident), "c")) {
2546 putBackToken(it, ident);
2547 } else {
2548 _ = try expectToken(it, tree, .RBracket);
2549 const node = try arena.create(Node.PrefixOp);
2550 node.* = .{
2551 .op_token = ident,
2552 .op = .{ .PtrType = .{} },
2553 .rhs = undefined, // set by caller
2554 };
2555 return &node.base;
2556 }
2557 }
2558 const sentinel = if (eatToken(it, .Colon)) |_|
2559 try expectNode(arena, it, tree, parseExpr, AstError{
2560 .ExpectedExpr = .{ .token = it.index },
2561 })
2562 else
2563 null;
2564 _ = try expectToken(it, tree, .RBracket);
2565 const node = try arena.create(Node.PrefixOp);
2566 node.* = .{
2567 .op_token = lbracket,
2568 .op = .{ .PtrType = .{ .sentinel = sentinel } },
2569 .rhs = undefined, // set by caller
2570 };
2571 return &node.base;
2572 }
2573 return null;
25332574}
25342575
25352576/// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
lib/std/zig/parser_test.zig+3-6
......@@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" {
15521552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
15531553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
15541554 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1555 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
15551556 \\
15561557 );
15571558}
......@@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" {
15621563 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
15631564 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
15641565 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1566 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
15651567 \\
15661568 );
15671569}
......@@ -1723,11 +1725,6 @@ test "zig fmt: multiline string" {
17231725 \\ \\two)
17241726 \\ \\three
17251727 \\ ;
1726 \\ const s2 =
1727 \\ c\\one
1728 \\ c\\two)
1729 \\ c\\three
1730 \\ ;
17311728 \\ const s3 = // hi
17321729 \\ \\one
17331730 \\ \\two)
......@@ -1744,7 +1741,6 @@ test "zig fmt: values" {
17441741 \\ 1;
17451742 \\ 1.0;
17461743 \\ "string";
1747 \\ c"cstring";
17481744 \\ 'c';
17491745 \\ true;
17501746 \\ false;
......@@ -1889,6 +1885,7 @@ test "zig fmt: arrays" {
18891885 \\ 2,
18901886 \\ };
18911887 \\ const a: [0]u8 = []u8{};
1888 \\ const x: [4:0]u8 = undefined;
18921889 \\}
18931890 \\
18941891 );
lib/std/zig/render.zig+32-8
......@@ -418,11 +418,27 @@ fn renderExpression(
418418
419419 switch (prefix_op_node.op) {
420420 ast.Node.PrefixOp.Op.PtrType => |ptr_info| {
421 const star_offset = switch (tree.tokens.at(prefix_op_node.op_token).id) {
422 Token.Id.AsteriskAsterisk => @as(usize, 1),
423 else => @as(usize, 0),
424 };
425 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *
421 const op_tok_id = tree.tokens.at(prefix_op_node.op_token).id;
422 switch (op_tok_id) {
423 .Asterisk, .AsteriskAsterisk => try stream.writeByte('*'),
424 .Identifier => try stream.write("[*c]"),
425 .LBracket => try stream.write("[*"),
426 else => unreachable,
427 }
428 if (ptr_info.sentinel) |sentinel| {
429 const colon_token = tree.prevToken(sentinel.firstToken());
430 try renderToken(tree, stream, colon_token, indent, start_col, Space.None); // :
431 const sentinel_space = switch (op_tok_id) {
432 .LBracket => Space.None,
433 else => Space.Space,
434 };
435 try renderExpression(allocator, stream, tree, indent, start_col, sentinel, sentinel_space);
436 }
437 switch (op_tok_id) {
438 .Asterisk, .AsteriskAsterisk, .Identifier => {},
439 .LBracket => try stream.writeByte(']'),
440 else => unreachable,
441 }
426442 if (ptr_info.allowzero_token) |allowzero_token| {
427443 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero
428444 }
......@@ -499,9 +515,12 @@ fn renderExpression(
499515 }
500516 },
501517
502 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
518 ast.Node.PrefixOp.Op.ArrayType => |array_info| {
503519 const lbracket = prefix_op_node.op_token;
504 const rbracket = tree.nextToken(array_index.lastToken());
520 const rbracket = tree.nextToken(if (array_info.sentinel) |sentinel|
521 sentinel.lastToken()
522 else
523 array_info.len_expr.lastToken());
505524
506525 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
507526
......@@ -509,13 +528,18 @@ fn renderExpression(
509528 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;
510529 const new_indent = if (ends_with_comment) indent + indent_delta else indent;
511530 const new_space = if (ends_with_comment) Space.Newline else Space.None;
512 try renderExpression(allocator, stream, tree, new_indent, start_col, array_index, new_space);
531 try renderExpression(allocator, stream, tree, new_indent, start_col, array_info.len_expr, new_space);
513532 if (starts_with_comment) {
514533 try stream.writeByte('\n');
515534 }
516535 if (ends_with_comment or starts_with_comment) {
517536 try stream.writeByteNTimes(' ', indent);
518537 }
538 if (array_info.sentinel) |sentinel| {
539 const colon_token = tree.prevToken(sentinel.firstToken());
540 try renderToken(tree, stream, colon_token, indent, start_col, Space.None); // :
541 try renderExpression(allocator, stream, tree, indent, start_col, sentinel, Space.None);
542 }
519543 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]
520544 },
521545 ast.Node.PrefixOp.Op.BitNot,
lib/std/zig/tokenizer.zig+11-73
......@@ -143,8 +143,6 @@ pub const Token = struct {
143143 LineComment,
144144 DocComment,
145145 ContainerDocComment,
146 BracketStarBracket,
147 BracketStarCBracket,
148146 ShebangLine,
149147 Keyword_align,
150148 Keyword_allowzero,
......@@ -269,8 +267,6 @@ pub const Token = struct {
269267 .AngleBracketAngleBracketRight => ">>",
270268 .AngleBracketAngleBracketRightEqual => ">>=",
271269 .Tilde => "~",
272 .BracketStarBracket => "[*]",
273 .BracketStarCBracket => "[*c]",
274270 .Keyword_align => "align",
275271 .Keyword_allowzero => "allowzero",
276272 .Keyword_and => "and",
......@@ -351,7 +347,6 @@ pub const Tokenizer = struct {
351347 Start,
352348 Identifier,
353349 Builtin,
354 C,
355350 StringLiteral,
356351 StringLiteralBackslash,
357352 MultilineStringLiteralLine,
......@@ -401,9 +396,6 @@ pub const Tokenizer = struct {
401396 Period,
402397 Period2,
403398 SawAtSign,
404 LBracket,
405 LBracketStar,
406 LBracketStarC,
407399 };
408400
409401 pub fn next(self: *Tokenizer) Token {
......@@ -427,10 +419,6 @@ pub const Tokenizer = struct {
427419 ' ', '\n', '\t', '\r' => {
428420 result.start = self.index + 1;
429421 },
430 'c' => {
431 state = State.C;
432 result.id = Token.Id.Identifier;
433 },
434422 '"' => {
435423 state = State.StringLiteral;
436424 result.id = Token.Id.StringLiteral;
......@@ -438,7 +426,7 @@ pub const Tokenizer = struct {
438426 '\'' => {
439427 state = State.CharLiteral;
440428 },
441 'a'...'b', 'd'...'z', 'A'...'Z', '_' => {
429 'a'...'z', 'A'...'Z', '_' => {
442430 state = State.Identifier;
443431 result.id = Token.Id.Identifier;
444432 },
......@@ -465,7 +453,9 @@ pub const Tokenizer = struct {
465453 break;
466454 },
467455 '[' => {
468 state = State.LBracket;
456 result.id = .LBracket;
457 self.index += 1;
458 break;
469459 },
470460 ']' => {
471461 result.id = Token.Id.RBracket;
......@@ -569,43 +559,6 @@ pub const Tokenizer = struct {
569559 },
570560 },
571561
572 State.LBracket => switch (c) {
573 '*' => {
574 state = State.LBracketStar;
575 },
576 else => {
577 result.id = Token.Id.LBracket;
578 break;
579 },
580 },
581
582 State.LBracketStar => switch (c) {
583 'c' => {
584 state = State.LBracketStarC;
585 },
586 ']' => {
587 result.id = Token.Id.BracketStarBracket;
588 self.index += 1;
589 break;
590 },
591 else => {
592 result.id = Token.Id.Invalid;
593 break;
594 },
595 },
596
597 State.LBracketStarC => switch (c) {
598 ']' => {
599 result.id = Token.Id.BracketStarCBracket;
600 self.index += 1;
601 break;
602 },
603 else => {
604 result.id = Token.Id.Invalid;
605 break;
606 },
607 },
608
609562 State.Ampersand => switch (c) {
610563 '&' => {
611564 result.id = Token.Id.Invalid_ampersands;
......@@ -730,20 +683,6 @@ pub const Tokenizer = struct {
730683 },
731684 else => break,
732685 },
733 State.C => switch (c) {
734 '\\' => {
735 state = State.Backslash;
736 result.id = Token.Id.MultilineStringLiteralLine;
737 },
738 '"' => {
739 state = State.StringLiteral;
740 result.id = Token.Id.StringLiteral;
741 },
742 'a'...'z', 'A'...'Z', '_', '0'...'9' => {
743 state = State.Identifier;
744 },
745 else => break,
746 },
747686 State.StringLiteral => switch (c) {
748687 '\\' => {
749688 state = State.StringLiteralBackslash;
......@@ -1204,7 +1143,6 @@ pub const Tokenizer = struct {
12041143 } else if (self.index == self.buffer.len) {
12051144 switch (state) {
12061145 State.Start,
1207 State.C,
12081146 State.IntegerLiteral,
12091147 State.IntegerLiteralWithRadix,
12101148 State.IntegerLiteralWithRadixHex,
......@@ -1247,8 +1185,6 @@ pub const Tokenizer = struct {
12471185 State.CharLiteralEnd,
12481186 State.CharLiteralUnicode,
12491187 State.StringLiteralBackslash,
1250 State.LBracketStar,
1251 State.LBracketStarC,
12521188 => {
12531189 result.id = Token.Id.Invalid;
12541190 },
......@@ -1265,9 +1201,6 @@ pub const Tokenizer = struct {
12651201 State.Slash => {
12661202 result.id = Token.Id.Slash;
12671203 },
1268 State.LBracket => {
1269 result.id = Token.Id.LBracket;
1270 },
12711204 State.Zero => {
12721205 result.id = Token.Id.IntegerLiteral;
12731206 },
......@@ -1388,9 +1321,14 @@ test "tokenizer - unknown length pointer and then c pointer" {
13881321 \\[*]u8
13891322 \\[*c]u8
13901323 , [_]Token.Id{
1391 Token.Id.BracketStarBracket,
1324 Token.Id.LBracket,
1325 Token.Id.Asterisk,
1326 Token.Id.RBracket,
1327 Token.Id.Identifier,
1328 Token.Id.LBracket,
1329 Token.Id.Asterisk,
13921330 Token.Id.Identifier,
1393 Token.Id.BracketStarCBracket,
1331 Token.Id.RBracket,
13941332 Token.Id.Identifier,
13951333 });
13961334}
src-self-hosted/clang.zig+3-3
......@@ -708,7 +708,7 @@ pub const ZigClangStringLiteral_StringKind = extern enum {
708708};
709709
710710pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
711pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
711pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8;
712712pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
713713pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
714714pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
......@@ -746,7 +746,7 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType
746746pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
747747pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
748748pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
749pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
749pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8;
750750pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
751751pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
752752pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
......@@ -904,7 +904,7 @@ pub extern fn ZigClangLoadFromCommandLine(
904904) ?*ZigClangASTUnit;
905905
906906pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
907pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;
907pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*:0]const u8;
908908
909909pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;
910910
src-self-hosted/codegen.zig+3-3
......@@ -52,7 +52,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
5252 u32(c.ZIG_VERSION_MINOR),
5353 u32(c.ZIG_VERSION_PATCH),
5454 );
55 const flags = c"";
55 const flags = "";
5656 const runtime_version = 0;
5757 const compile_unit_file = llvm.CreateFile(
5858 dibuilder,
......@@ -68,7 +68,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
6868 is_optimized,
6969 flags,
7070 runtime_version,
71 c"",
71 "",
7272 0,
7373 !comp.strip,
7474 ) orelse return error.OutOfMemory;
......@@ -402,7 +402,7 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Poin
402402 if (child_type.handleIsPtr()) {
403403 return ptr;
404404 }
405 return try renderLoad(ofile, ptr, ptr_type, c"");
405 return try renderLoad(ofile, ptr, ptr_type, "");
406406}
407407
408408pub fn renderStoreUntyped(
src-self-hosted/compilation.zig+5-5
......@@ -490,8 +490,8 @@ pub const Compilation = struct {
490490 // LLVM creates invalid binaries on Windows sometimes.
491491 // See https://github.com/ziglang/zig/issues/508
492492 // As a workaround we do not use target native features on Windows.
493 var target_specific_cpu_args: ?[*]u8 = null;
494 var target_specific_cpu_features: ?[*]u8 = null;
493 var target_specific_cpu_args: ?[*:0]u8 = null;
494 var target_specific_cpu_features: ?[*:0]u8 = null;
495495 defer llvm.DisposeMessage(target_specific_cpu_args);
496496 defer llvm.DisposeMessage(target_specific_cpu_features);
497497 if (target == Target.Native and !target.isWindows()) {
......@@ -501,9 +501,9 @@ pub const Compilation = struct {
501501
502502 comp.target_machine = llvm.CreateTargetMachine(
503503 comp.llvm_target,
504 comp.llvm_triple.ptr(),
505 target_specific_cpu_args orelse c"",
506 target_specific_cpu_features orelse c"",
504 comp.llvm_triple.toSliceConst(),
505 target_specific_cpu_args orelse "",
506 target_specific_cpu_features orelse "",
507507 opt_level,
508508 reloc_mode,
509509 llvm.CodeModelDefault,
src-self-hosted/ir.zig+6-6
......@@ -330,7 +330,7 @@ pub const Inst = struct {
330330 @intCast(c_uint, args.len),
331331 llvm_cc,
332332 fn_inline,
333 c"",
333 "",
334334 ) orelse error.OutOfMemory;
335335 }
336336 };
......@@ -1409,7 +1409,7 @@ pub const Builder = struct {
14091409 if (block.label) |label| {
14101410 block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena());
14111411 block_scope.incoming_blocks = std.ArrayList(*BasicBlock).init(irb.arena());
1412 block_scope.end_block = try irb.createBasicBlock(parent_scope, c"BlockEnd");
1412 block_scope.end_block = try irb.createBasicBlock(parent_scope, "BlockEnd");
14131413 block_scope.is_comptime = try irb.buildConstBool(
14141414 parent_scope,
14151415 Span.token(block.lbrace),
......@@ -1541,8 +1541,8 @@ pub const Builder = struct {
15411541 const defer_counts = irb.countDefers(scope, outer_scope);
15421542 const have_err_defers = defer_counts.error_exit != 0;
15431543 if (have_err_defers or irb.comp.have_err_ret_tracing) {
1544 const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");
1545 const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");
1544 const err_block = try irb.createBasicBlock(scope, "ErrRetErr");
1545 const ok_block = try irb.createBasicBlock(scope, "ErrRetOk");
15461546 if (!have_err_defers) {
15471547 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
15481548 }
......@@ -1563,7 +1563,7 @@ pub const Builder = struct {
15631563 .is_comptime = err_is_comptime,
15641564 });
15651565
1566 const ret_stmt_block = try irb.createBasicBlock(scope, c"RetStmt");
1566 const ret_stmt_block = try irb.createBasicBlock(scope, "RetStmt");
15671567
15681568 try irb.setCursorAtEndAndAppendBlock(err_block);
15691569 if (have_err_defers) {
......@@ -2528,7 +2528,7 @@ pub async fn gen(
25282528 var irb = try Builder.init(comp, tree_scope, scope);
25292529 errdefer irb.abort();
25302530
2531 const entry_block = try irb.createBasicBlock(scope, c"Entry");
2531 const entry_block = try irb.createBasicBlock(scope, "Entry");
25322532 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
25332533 try irb.setCursorAtEndAndAppendBlock(entry_block);
25342534
src-self-hosted/link.zig+63-63
......@@ -55,7 +55,7 @@ pub async fn link(comp: *Compilation) !void {
5555
5656 // even though we're calling LLD as a library it thinks the first
5757 // argument is its own exe name
58 try ctx.args.append(c"lld");
58 try ctx.args.append("lld");
5959
6060 if (comp.haveLibC()) {
6161 ctx.libc = ctx.comp.override_libc orelse blk: {
......@@ -145,7 +145,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
145145 // lj->args.append("-T");
146146 // lj->args.append(g->linker_script);
147147 //}
148 try ctx.args.append(c"--gc-sections");
148 try ctx.args.append("--gc-sections");
149149
150150 //lj->args.append("-m");
151151 //lj->args.append(getLDMOption(&g->zig_target));
......@@ -155,9 +155,9 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
155155 //Buf *soname = nullptr;
156156 if (ctx.comp.is_static) {
157157 if (util.isArmOrThumb(ctx.comp.target)) {
158 try ctx.args.append(c"-Bstatic");
158 try ctx.args.append("-Bstatic");
159159 } else {
160 try ctx.args.append(c"-static");
160 try ctx.args.append("-static");
161161 }
162162 }
163163 //} else if (shared) {
......@@ -170,7 +170,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
170170 // soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
171171 //}
172172
173 try ctx.args.append(c"-o");
173 try ctx.args.append("-o");
174174 try ctx.args.append(ctx.out_file_path.ptr());
175175
176176 if (ctx.link_in_crt) {
......@@ -213,10 +213,10 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
213213 //}
214214
215215 if (ctx.comp.haveLibC()) {
216 try ctx.args.append(c"-L");
216 try ctx.args.append("-L");
217217 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
218218
219 try ctx.args.append(c"-L");
219 try ctx.args.append("-L");
220220 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
221221
222222 if (!ctx.comp.is_static) {
......@@ -225,7 +225,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
225225 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
226226 return error.LibCMissingDynamicLinker;
227227 };
228 try ctx.args.append(c"-dynamic-linker");
228 try ctx.args.append("-dynamic-linker");
229229 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
230230 }
231231 }
......@@ -272,23 +272,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
272272 // libc dep
273273 if (ctx.comp.haveLibC()) {
274274 if (ctx.comp.is_static) {
275 try ctx.args.append(c"--start-group");
276 try ctx.args.append(c"-lgcc");
277 try ctx.args.append(c"-lgcc_eh");
278 try ctx.args.append(c"-lc");
279 try ctx.args.append(c"-lm");
280 try ctx.args.append(c"--end-group");
275 try ctx.args.append("--start-group");
276 try ctx.args.append("-lgcc");
277 try ctx.args.append("-lgcc_eh");
278 try ctx.args.append("-lc");
279 try ctx.args.append("-lm");
280 try ctx.args.append("--end-group");
281281 } else {
282 try ctx.args.append(c"-lgcc");
283 try ctx.args.append(c"--as-needed");
284 try ctx.args.append(c"-lgcc_s");
285 try ctx.args.append(c"--no-as-needed");
286 try ctx.args.append(c"-lc");
287 try ctx.args.append(c"-lm");
288 try ctx.args.append(c"-lgcc");
289 try ctx.args.append(c"--as-needed");
290 try ctx.args.append(c"-lgcc_s");
291 try ctx.args.append(c"--no-as-needed");
282 try ctx.args.append("-lgcc");
283 try ctx.args.append("--as-needed");
284 try ctx.args.append("-lgcc_s");
285 try ctx.args.append("--no-as-needed");
286 try ctx.args.append("-lc");
287 try ctx.args.append("-lm");
288 try ctx.args.append("-lgcc");
289 try ctx.args.append("--as-needed");
290 try ctx.args.append("-lgcc_s");
291 try ctx.args.append("--no-as-needed");
292292 }
293293 }
294294
......@@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
299299 }
300300
301301 if (ctx.comp.target != Target.Native) {
302 try ctx.args.append(c"--allow-shlib-undefined");
302 try ctx.args.append("--allow-shlib-undefined");
303303 }
304304
305305 if (ctx.comp.target.getOs() == .zen) {
306 try ctx.args.append(c"-e");
307 try ctx.args.append(c"_start");
306 try ctx.args.append("-e");
307 try ctx.args.append("_start");
308308
309 try ctx.args.append(c"--image-base=0x10000000");
309 try ctx.args.append("--image-base=0x10000000");
310310 }
311311}
312312
......@@ -317,23 +317,23 @@ fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
317317}
318318
319319fn constructLinkerArgsCoff(ctx: *Context) !void {
320 try ctx.args.append(c"-NOLOGO");
320 try ctx.args.append("-NOLOGO");
321321
322322 if (!ctx.comp.strip) {
323 try ctx.args.append(c"-DEBUG");
323 try ctx.args.append("-DEBUG");
324324 }
325325
326326 switch (ctx.comp.target.getArch()) {
327 .i386 => try ctx.args.append(c"-MACHINE:X86"),
328 .x86_64 => try ctx.args.append(c"-MACHINE:X64"),
329 .aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
327 .i386 => try ctx.args.append("-MACHINE:X86"),
328 .x86_64 => try ctx.args.append("-MACHINE:X64"),
329 .aarch64 => try ctx.args.append("-MACHINE:ARM"),
330330 else => return error.UnsupportedLinkArchitecture,
331331 }
332332
333333 if (ctx.comp.windows_subsystem_windows) {
334 try ctx.args.append(c"/SUBSYSTEM:windows");
334 try ctx.args.append("/SUBSYSTEM:windows");
335335 } else if (ctx.comp.windows_subsystem_console) {
336 try ctx.args.append(c"/SUBSYSTEM:console");
336 try ctx.args.append("/SUBSYSTEM:console");
337337 }
338338
339339 const is_library = ctx.comp.kind == .Lib;
......@@ -367,14 +367,14 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
367367
368368 // Visual C++ 2015 Conformance Changes
369369 // https://msdn.microsoft.com/en-us/library/bb531344.aspx
370 try ctx.args.append(c"legacy_stdio_definitions.lib");
370 try ctx.args.append("legacy_stdio_definitions.lib");
371371
372372 // msvcrt depends on kernel32
373 try ctx.args.append(c"kernel32.lib");
373 try ctx.args.append("kernel32.lib");
374374 } else {
375 try ctx.args.append(c"-NODEFAULTLIB");
375 try ctx.args.append("-NODEFAULTLIB");
376376 if (!is_library) {
377 try ctx.args.append(c"-ENTRY:WinMainCRTStartup");
377 try ctx.args.append("-ENTRY:WinMainCRTStartup");
378378 // TODO
379379 //if (g->have_winmain) {
380380 // lj->args.append("-ENTRY:WinMain");
......@@ -385,7 +385,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
385385 }
386386
387387 if (is_library and !ctx.comp.is_static) {
388 try ctx.args.append(c"-DLL");
388 try ctx.args.append("-DLL");
389389 }
390390
391391 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
......@@ -463,18 +463,18 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
463463}
464464
465465fn constructLinkerArgsMachO(ctx: *Context) !void {
466 try ctx.args.append(c"-demangle");
466 try ctx.args.append("-demangle");
467467
468468 if (ctx.comp.linker_rdynamic) {
469 try ctx.args.append(c"-export_dynamic");
469 try ctx.args.append("-export_dynamic");
470470 }
471471
472472 const is_lib = ctx.comp.kind == .Lib;
473473 const shared = !ctx.comp.is_static and is_lib;
474474 if (ctx.comp.is_static) {
475 try ctx.args.append(c"-static");
475 try ctx.args.append("-static");
476476 } else {
477 try ctx.args.append(c"-dynamic");
477 try ctx.args.append("-dynamic");
478478 }
479479
480480 //if (is_lib) {
......@@ -503,7 +503,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
503503 // }
504504 //}
505505
506 try ctx.args.append(c"-arch");
506 try ctx.args.append("-arch");
507507 const darwin_arch_str = try std.cstr.addNullByte(
508508 &ctx.arena.allocator,
509509 ctx.comp.target.getDarwinArchString(),
......@@ -512,22 +512,22 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
512512
513513 const platform = try DarwinPlatform.get(ctx.comp);
514514 switch (platform.kind) {
515 .MacOS => try ctx.args.append(c"-macosx_version_min"),
516 .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
517 .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
515 .MacOS => try ctx.args.append("-macosx_version_min"),
516 .IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
517 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
518518 }
519519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
520520 try ctx.args.append(ver_str.ptr);
521521
522522 if (ctx.comp.kind == .Exe) {
523523 if (ctx.comp.is_static) {
524 try ctx.args.append(c"-no_pie");
524 try ctx.args.append("-no_pie");
525525 } else {
526 try ctx.args.append(c"-pie");
526 try ctx.args.append("-pie");
527527 }
528528 }
529529
530 try ctx.args.append(c"-o");
530 try ctx.args.append("-o");
531531 try ctx.args.append(ctx.out_file_path.ptr());
532532
533533 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
......@@ -537,27 +537,27 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
537537 //add_rpath(lj, &lj->out_file);
538538
539539 if (shared) {
540 try ctx.args.append(c"-headerpad_max_install_names");
540 try ctx.args.append("-headerpad_max_install_names");
541541 } else if (ctx.comp.is_static) {
542 try ctx.args.append(c"-lcrt0.o");
542 try ctx.args.append("-lcrt0.o");
543543 } else {
544544 switch (platform.kind) {
545545 .MacOS => {
546546 if (platform.versionLessThan(10, 5)) {
547 try ctx.args.append(c"-lcrt1.o");
547 try ctx.args.append("-lcrt1.o");
548548 } else if (platform.versionLessThan(10, 6)) {
549 try ctx.args.append(c"-lcrt1.10.5.o");
549 try ctx.args.append("-lcrt1.10.5.o");
550550 } else if (platform.versionLessThan(10, 8)) {
551 try ctx.args.append(c"-lcrt1.10.6.o");
551 try ctx.args.append("-lcrt1.10.6.o");
552552 }
553553 },
554554 .IPhoneOS => {
555555 if (ctx.comp.target.getArch() == .aarch64) {
556556 // iOS does not need any crt1 files for arm64
557557 } else if (platform.versionLessThan(3, 1)) {
558 try ctx.args.append(c"-lcrt1.o");
558 try ctx.args.append("-lcrt1.o");
559559 } else if (platform.versionLessThan(6, 0)) {
560 try ctx.args.append(c"-lcrt1.3.1.o");
560 try ctx.args.append("-lcrt1.3.1.o");
561561 }
562562 },
563563 .IPhoneOSSimulator => {}, // no crt1.o needed
......@@ -589,7 +589,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
589589 // to make syscalls because the syscall numbers are not documented
590590 // and change between versions.
591591 // so we always link against libSystem
592 try ctx.args.append(c"-lSystem");
592 try ctx.args.append("-lSystem");
593593 } else {
594594 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
595595 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
......@@ -601,15 +601,15 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
601601 }
602602 }
603603 } else {
604 try ctx.args.append(c"-undefined");
605 try ctx.args.append(c"dynamic_lookup");
604 try ctx.args.append("-undefined");
605 try ctx.args.append("dynamic_lookup");
606606 }
607607
608608 if (platform.kind == .MacOS) {
609609 if (platform.versionLessThan(10, 5)) {
610 try ctx.args.append(c"-lgcc_s.10.4");
610 try ctx.args.append("-lgcc_s.10.4");
611611 } else if (platform.versionLessThan(10, 6)) {
612 try ctx.args.append(c"-lgcc_s.10.5");
612 try ctx.args.append("-lgcc_s.10.5");
613613 }
614614 } else {
615615 @panic("TODO");
src-self-hosted/llvm.zig+22-22
......@@ -83,16 +83,16 @@ pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
8383pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
8484
8585pub const AddGlobal = LLVMAddGlobal;
86extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
86extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value;
8787
8888pub const ConstStringInContext = LLVMConstStringInContext;
89extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
89extern fn LLVMConstStringInContext(C: *Context, Str: [*:0]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
9090
9191pub const ConstInt = LLVMConstInt;
9292extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
9393
9494pub const BuildLoad = LLVMBuildLoad;
95extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
95extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*:0]const u8) ?*Value;
9696
9797pub const ConstNull = LLVMConstNull;
9898extern fn LLVMConstNull(Ty: *Type) ?*Value;
......@@ -110,24 +110,24 @@ pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
110110extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
111111
112112pub const AddFunction = LLVMAddFunction;
113extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
113extern fn LLVMAddFunction(M: *Module, Name: [*:0]const u8, FunctionTy: *Type) ?*Value;
114114
115115pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
116116extern fn ZigLLVMCreateCompileUnit(
117117 dibuilder: *DIBuilder,
118118 lang: c_uint,
119119 difile: *DIFile,
120 producer: [*]const u8,
120 producer: [*:0]const u8,
121121 is_optimized: bool,
122 flags: [*]const u8,
122 flags: [*:0]const u8,
123123 runtime_version: c_uint,
124 split_name: [*]const u8,
124 split_name: [*:0]const u8,
125125 dwo_id: u64,
126126 emit_debug_info: bool,
127127) ?*DICompileUnit;
128128
129129pub const CreateFile = ZigLLVMCreateFile;
130extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
130extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*:0]const u8, directory: [*:0]const u8) ?*DIFile;
131131
132132pub const ArrayType = LLVMArrayType;
133133extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
......@@ -145,7 +145,7 @@ pub const IntTypeInContext = LLVMIntTypeInContext;
145145extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
146146
147147pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
148extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
148extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *Context) ?*Module;
149149
150150pub const VoidTypeInContext = LLVMVoidTypeInContext;
151151extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
......@@ -157,7 +157,7 @@ pub const ContextDispose = LLVMContextDispose;
157157extern fn LLVMContextDispose(C: *Context) void;
158158
159159pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
160extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
160extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*:0]u8;
161161
162162pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
163163extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
......@@ -165,9 +165,9 @@ extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
165165pub const CreateTargetMachine = ZigLLVMCreateTargetMachine;
166166extern fn ZigLLVMCreateTargetMachine(
167167 T: *Target,
168 Triple: [*]const u8,
169 CPU: [*]const u8,
170 Features: [*]const u8,
168 Triple: [*:0]const u8,
169 CPU: [*:0]const u8,
170 Features: [*:0]const u8,
171171 Level: CodeGenOptLevel,
172172 Reloc: RelocMode,
173173 CodeModel: CodeModel,
......@@ -175,10 +175,10 @@ extern fn ZigLLVMCreateTargetMachine(
175175) ?*TargetMachine;
176176
177177pub const GetHostCPUName = LLVMGetHostCPUName;
178extern fn LLVMGetHostCPUName() ?[*]u8;
178extern fn LLVMGetHostCPUName() ?[*:0]u8;
179179
180180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
181extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
181extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
182182
183183pub const GetElementType = LLVMGetElementType;
184184extern fn LLVMGetElementType(Ty: *Type) *Type;
......@@ -190,16 +190,16 @@ pub const BuildStore = LLVMBuildStore;
190190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
191191
192192pub const BuildAlloca = LLVMBuildAlloca;
193extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
193extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*:0]const u8) ?*Value;
194194
195195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
196196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
197197
198198pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
199extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
199extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **Target, ErrorMessage: ?*[*:0]u8) Bool;
200200
201201pub const VerifyModule = LLVMVerifyModule;
202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
202extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*:0]u8) Bool;
203203
204204pub const GetInsertBlock = LLVMGetInsertBlock;
205205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
......@@ -216,7 +216,7 @@ pub const GetParam = LLVMGetParam;
216216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
217217
218218pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
219extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
219extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) ?*BasicBlock;
220220
221221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
222222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
......@@ -278,14 +278,14 @@ pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
278278extern fn ZigLLVMTargetMachineEmitToFile(
279279 targ_machine_ref: *TargetMachine,
280280 module_ref: *Module,
281 filename: [*]const u8,
281 filename: [*:0]const u8,
282282 output_type: EmitOutputType,
283 error_message: *[*]u8,
283 error_message: *[*:0]u8,
284284 is_debug: bool,
285285 is_small: bool,
286286) bool;
287287
288288pub const BuildCall = ZigLLVMBuildCall;
289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
289extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*:0]const u8) ?*Value;
290290
291291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/stage1.zig+3-3
......@@ -27,7 +27,7 @@ comptime {
2727// ABI warning
2828export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
2929 const info_zen = @import("main.zig").info_zen;
30 ptr.* = &info_zen;
30 ptr.* = info_zen;
3131 len.* = info_zen.len;
3232}
3333
......@@ -144,7 +144,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
144144
145145// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
146146// we use a blocking implementation.
147export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
147export fn stage2_fmt(argc: c_int, argv: [*]const [*:0]const u8) c_int {
148148 if (std.debug.runtime_safety) {
149149 fmtMain(argc, argv) catch unreachable;
150150 } else {
......@@ -156,7 +156,7 @@ export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
156156 return 0;
157157}
158158
159fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void {
159fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
160160 const allocator = std.heap.c_allocator;
161161 var args_list = std.ArrayList([]const u8).init(allocator);
162162 const argc_usize = @intCast(usize, argc);
src-self-hosted/translate_c.zig+24-13
......@@ -113,7 +113,7 @@ const Context = struct {
113113 }
114114
115115 /// Convert a null-terminated C string to a slice allocated in the arena
116 fn str(c: *Context, s: [*]const u8) ![]u8 {
116 fn str(c: *Context, s: [*:0]const u8) ![]u8 {
117117 return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));
118118 }
119119
......@@ -696,10 +696,9 @@ fn transStringLiteral(
696696 len = 0;
697697 for (str) |c| len += escapeChar(c, &char_buf).len;
698698
699 const buf = try rp.c.a().alloc(u8, len + "c\"\"".len);
700 buf[0] = 'c';
701 buf[1] = '"';
702 writeEscapedString(buf[2..], str);
699 const buf = try rp.c.a().alloc(u8, len + "\"\"".len);
700 buf[0] = '"';
701 writeEscapedString(buf[1..], str);
703702 buf[buf.len - 1] = '"';
704703
705704 const token = try appendToken(rp.c, .StringLiteral, buf);
......@@ -1104,16 +1103,30 @@ fn transCreateNodePtrType(
11041103 is_const: bool,
11051104 is_volatile: bool,
11061105 op_tok_id: std.zig.Token.Id,
1107 bytes: []const u8,
11081106) !*ast.Node.PrefixOp {
11091107 const node = try c.a().create(ast.Node.PrefixOp);
1108 const op_token = switch (op_tok_id) {
1109 .LBracket => blk: {
1110 const lbracket = try appendToken(c, .LBracket, "[");
1111 _ = try appendToken(c, .Asterisk, "*");
1112 _ = try appendToken(c, .RBracket, "]");
1113 break :blk lbracket;
1114 },
1115 .Identifier => blk: {
1116 _ = try appendToken(c, .LBracket, "[");
1117 _ = try appendToken(c, .Asterisk, "*");
1118 const c_ident = try appendToken(c, .Identifier, "c");
1119 _ = try appendToken(c, .RBracket, "]");
1120 break :blk c_ident;
1121 },
1122 .Asterisk => try appendToken(c, .Asterisk, "*"),
1123 else => unreachable,
1124 };
11101125 node.* = ast.Node.PrefixOp{
11111126 .base = ast.Node{ .id = .PrefixOp },
1112 .op_token = try appendToken(c, op_tok_id, bytes),
1127 .op_token = op_token,
11131128 .op = ast.Node.PrefixOp.Op{
1114 .PtrType = ast.Node.PrefixOp.PtrInfo{
1115 .allowzero_token = null,
1116 .align_info = null,
1129 .PtrType = .{
11171130 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
11181131 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
11191132 },
......@@ -1224,7 +1237,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
12241237 ZigClangQualType_isConstQualified(child_qt),
12251238 ZigClangQualType_isVolatileQualified(child_qt),
12261239 .Asterisk,
1227 "*",
12281240 );
12291241 optional_node.rhs = &pointer_node.base;
12301242 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
......@@ -1234,8 +1246,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
12341246 rp.c,
12351247 ZigClangQualType_isConstQualified(child_qt),
12361248 ZigClangQualType_isVolatileQualified(child_qt),
1237 .BracketStarCBracket,
1238 "[*c]",
1249 .Identifier,
12391250 );
12401251 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
12411252 return &pointer_node.base;
src-self-hosted/util.zig+3-3
......@@ -172,9 +172,9 @@ pub fn getDarwinArchString(self: Target) []const u8 {
172172
173173pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
174174 var result: *llvm.Target = undefined;
175 var err_msg: [*]u8 = undefined;
176 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
177 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
175 var err_msg: [*:0]u8 = undefined;
176 if (llvm.GetTargetFromTriple(triple.toSlice(), &result, &err_msg) != 0) {
177 std.debug.warn("triple: {s} error: {s}\n", triple.toSlice(), err_msg);
178178 return error.UnsupportedTarget;
179179 }
180180 return result;
src-self-hosted/value.zig+1-1
......@@ -473,7 +473,7 @@ pub const Value = struct {
473473 dont_null_terminate,
474474 ) orelse return error.OutOfMemory;
475475 const str_init_type = llvm.TypeOf(llvm_str_init);
476 const global = llvm.AddGlobal(ofile.module, str_init_type, c"") orelse return error.OutOfMemory;
476 const global = llvm.AddGlobal(ofile.module, str_init_type, "") orelse return error.OutOfMemory;
477477 llvm.SetInitializer(global, llvm_str_init);
478478 llvm.SetLinkage(global, llvm.PrivateLinkage);
479479 llvm.SetGlobalConstant(global, 1);
src/all_types.hpp+25-4
......@@ -101,6 +101,10 @@ struct IrExecutable {
101101 bool is_inline;
102102 bool is_generic_instantiation;
103103 bool need_err_code_spill;
104
105 // This is a function for use in the debugger to print
106 // the source location.
107 void src();
104108};
105109
106110enum OutType {
......@@ -236,9 +240,6 @@ struct ConstPtrValue {
236240 struct {
237241 ConstExprValue *array_val;
238242 size_t elem_index;
239 // This helps us preserve the null byte when performing compile-time
240 // concatenation on C strings.
241 bool is_cstr;
242243 } base_array;
243244 struct {
244245 ConstExprValue *struct_val;
......@@ -351,6 +352,7 @@ struct LazyValueSliceType {
351352 LazyValue base;
352353
353354 IrAnalyze *ira;
355 IrInstruction *sentinel; // can be null
354356 IrInstruction *elem_type;
355357 IrInstruction *align_inst; // can be null
356358
......@@ -363,6 +365,7 @@ struct LazyValuePtrType {
363365 LazyValue base;
364366
365367 IrAnalyze *ira;
368 IrInstruction *sentinel; // can be null
366369 IrInstruction *elem_type;
367370 IrInstruction *align_inst; // can be null
368371
......@@ -598,6 +601,7 @@ enum NodeType {
598601 NodeTypeSuspend,
599602 NodeTypeAnyFrameType,
600603 NodeTypeEnumLiteral,
604 NodeTypeVarFieldType,
601605};
602606
603607enum CallingConvention {
......@@ -818,6 +822,7 @@ struct AstNodePrefixOpExpr {
818822
819823struct AstNodePointerType {
820824 Token *star_token;
825 AstNode *sentinel;
821826 AstNode *align_expr;
822827 BigInt *bit_offset_start;
823828 BigInt *host_int_bytes;
......@@ -828,11 +833,13 @@ struct AstNodePointerType {
828833};
829834
830835struct AstNodeInferredArrayType {
836 AstNode *sentinel; // can be null
831837 AstNode *child_type;
832838};
833839
834840struct AstNodeArrayType {
835841 AstNode *size;
842 AstNode *sentinel;
836843 AstNode *child_type;
837844 AstNode *align_expr;
838845 Token *allow_zero_token;
......@@ -997,7 +1004,6 @@ struct AstNodeStructField {
9971004
9981005struct AstNodeStringLiteral {
9991006 Buf *buf;
1000 bool c;
10011007};
10021008
10031009struct AstNodeCharLiteral {
......@@ -1204,6 +1210,11 @@ struct ZigTypePointer {
12041210 // struct.
12051211 InferredStructField *inferred_struct_field;
12061212
1213 // This can be null. If it is non-null, it means the pointer is terminated by this
1214 // sentinel value. This is most commonly used for C-style strings, with a 0 byte
1215 // to specify the length of the memory pointed to.
1216 ConstExprValue *sentinel;
1217
12071218 PtrLen ptr_len;
12081219 uint32_t explicit_alignment; // 0 means use ABI alignment
12091220
......@@ -1231,6 +1242,7 @@ struct ZigTypeFloat {
12311242struct ZigTypeArray {
12321243 ZigType *child_type;
12331244 uint64_t len;
1245 ConstExprValue *sentinel;
12341246};
12351247
12361248struct TypeStructField {
......@@ -1756,8 +1768,10 @@ struct TypeId {
17561768
17571769 union {
17581770 struct {
1771 CodeGen *codegen;
17591772 ZigType *child_type;
17601773 InferredStructField *inferred_struct_field;
1774 ConstExprValue *sentinel;
17611775 PtrLen ptr_len;
17621776 uint32_t alignment;
17631777
......@@ -1770,8 +1784,10 @@ struct TypeId {
17701784 bool allow_zero;
17711785 } pointer;
17721786 struct {
1787 CodeGen *codegen;
17731788 ZigType *child_type;
17741789 uint64_t size;
1790 ConstExprValue *sentinel;
17751791 } array;
17761792 struct {
17771793 bool is_signed;
......@@ -1950,6 +1966,7 @@ struct CodeGen {
19501966 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
19511967 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
19521968 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
1969 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> one_possible_values;
19531970
19541971 ZigList<Tld *> resolve_queue;
19551972 size_t resolve_queue_index;
......@@ -2026,6 +2043,7 @@ struct CodeGen {
20262043 IrInstruction *invalid_instruction;
20272044 IrInstruction *unreach_instruction;
20282045
2046 ConstExprValue const_zero_byte;
20292047 ConstExprValue const_void_val;
20302048 ConstExprValue panic_msg_vals[PanicMsgIdCount];
20312049
......@@ -2982,12 +3000,14 @@ struct IrInstructionArrayType {
29823000 IrInstruction base;
29833001
29843002 IrInstruction *size;
3003 IrInstruction *sentinel;
29853004 IrInstruction *child_type;
29863005};
29873006
29883007struct IrInstructionPtrType {
29893008 IrInstruction base;
29903009
3010 IrInstruction *sentinel;
29913011 IrInstruction *align_value;
29923012 IrInstruction *child_type;
29933013 uint32_t bit_offset_start;
......@@ -3007,6 +3027,7 @@ struct IrInstructionAnyFrameType {
30073027struct IrInstructionSliceType {
30083028 IrInstruction base;
30093029
3030 IrInstruction *sentinel;
30103031 IrInstruction *align_value;
30113032 IrInstruction *child_type;
30123033 bool is_const;
src/analyze.cpp+199-156
......@@ -452,18 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
452452 return entry;
453453}
454454
455static const char *ptr_len_to_star_str(PtrLen ptr_len) {
456 switch (ptr_len) {
457 case PtrLenSingle:
458 return "*";
459 case PtrLenUnknown:
460 return "[*]";
461 case PtrLenC:
462 return "[*c]";
463 }
464 zig_unreachable();
465}
466
467455ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
468456 if (fn->frame_type != nullptr) {
469457 return fn->frame_type;
......@@ -483,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
483471 return entry;
484472}
485473
474static void append_ptr_type_attrs(Buf *type_name, ZigType *ptr_type) {
475 const char *const_str = ptr_type->data.pointer.is_const ? "const " : "";
476 const char *volatile_str = ptr_type->data.pointer.is_volatile ? "volatile " : "";
477 const char *allow_zero_str;
478 if (ptr_type->data.pointer.ptr_len == PtrLenC) {
479 assert(ptr_type->data.pointer.allow_zero);
480 allow_zero_str = "";
481 } else {
482 allow_zero_str = ptr_type->data.pointer.allow_zero ? "allowzero " : "";
483 }
484 if (ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.host_int_bytes != 0 ||
485 ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE)
486 {
487 buf_appendf(type_name, "align(");
488 if (ptr_type->data.pointer.explicit_alignment != 0) {
489 buf_appendf(type_name, "%" PRIu32, ptr_type->data.pointer.explicit_alignment);
490 }
491 if (ptr_type->data.pointer.host_int_bytes != 0) {
492 buf_appendf(type_name, ":%" PRIu32 ":%" PRIu32, ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes);
493 }
494 if (ptr_type->data.pointer.vector_index == VECTOR_INDEX_RUNTIME) {
495 buf_appendf(type_name, ":?");
496 } else if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) {
497 buf_appendf(type_name, ":%" PRIu32, ptr_type->data.pointer.vector_index);
498 }
499 buf_appendf(type_name, ") ");
500 }
501 buf_appendf(type_name, "%s%s%s", const_str, volatile_str, allow_zero_str);
502 if (ptr_type->data.pointer.inferred_struct_field != nullptr) {
503 buf_appendf(type_name, " field '%s' of %s)",
504 buf_ptr(ptr_type->data.pointer.inferred_struct_field->field_name),
505 buf_ptr(&ptr_type->data.pointer.inferred_struct_field->inferred_struct_type->name));
506 } else {
507 buf_appendf(type_name, "%s", buf_ptr(&ptr_type->data.pointer.child_type->name));
508 }
509}
510
486511ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
487512 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
488513 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,
489 uint32_t vector_index, InferredStructField *inferred_struct_field)
514 uint32_t vector_index, InferredStructField *inferred_struct_field, ConstExprValue *sentinel)
490515{
491516 assert(ptr_len != PtrLenC || allow_zero);
492517 assert(!type_is_invalid(child_type));
......@@ -509,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
509534 TypeId type_id = {};
510535 ZigType **parent_pointer = nullptr;
511536 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
512 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr)
537 allow_zero || vector_index != VECTOR_INDEX_NONE || inferred_struct_field != nullptr ||
538 sentinel != nullptr)
513539 {
514540 type_id.id = ZigTypeIdPointer;
541 type_id.data.pointer.codegen = g;
515542 type_id.data.pointer.child_type = child_type;
516543 type_id.data.pointer.is_const = is_const;
517544 type_id.data.pointer.is_volatile = is_volatile;
......@@ -522,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
522549 type_id.data.pointer.allow_zero = allow_zero;
523550 type_id.data.pointer.vector_index = vector_index;
524551 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
552 type_id.data.pointer.sentinel = sentinel;
525553
526554 auto existing_entry = g->type_table.maybe_get(type_id);
527555 if (existing_entry)
......@@ -537,56 +565,35 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
537565
538566 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
539567
540 const char *star_str = ptr_len_to_star_str(ptr_len);
541 const char *const_str = is_const ? "const " : "";
542 const char *volatile_str = is_volatile ? "volatile " : "";
543 const char *allow_zero_str;
544 if (ptr_len == PtrLenC) {
545 assert(allow_zero);
546 allow_zero_str = "";
547 } else {
548 allow_zero_str = allow_zero ? "allowzero " : "";
549 }
550568 buf_resize(&entry->name, 0);
551 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {
552 if (inferred_struct_field == nullptr) {
553 buf_appendf(&entry->name, "%s%s%s%s%s",
554 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
555 } else {
556 buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)",
557 star_str, const_str, volatile_str, allow_zero_str,
558 buf_ptr(inferred_struct_field->field_name),
559 buf_ptr(&inferred_struct_field->inferred_struct_type->name));
560 }
561 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {
562 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
563 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
564 } else if (byte_alignment == 0) {
565 assert(vector_index == VECTOR_INDEX_NONE);
566 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
567 star_str,
568 bit_offset_in_host, host_int_bytes,
569 const_str, volatile_str, allow_zero_str,
570 buf_ptr(&child_type->name));
571 } else if (vector_index == VECTOR_INDEX_NONE) {
572 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
573 star_str, byte_alignment,
574 bit_offset_in_host, host_int_bytes,
575 const_str, volatile_str, allow_zero_str,
576 buf_ptr(&child_type->name));
577 } else if (vector_index == VECTOR_INDEX_RUNTIME) {
578 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":?) %s%s%s%s",
579 star_str, byte_alignment,
580 bit_offset_in_host, host_int_bytes,
581 const_str, volatile_str, allow_zero_str,
582 buf_ptr(&child_type->name));
583 } else {
584 buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s",
585 star_str, byte_alignment,
586 bit_offset_in_host, host_int_bytes, vector_index,
587 const_str, volatile_str, allow_zero_str,
588 buf_ptr(&child_type->name));
569 if (inferred_struct_field != nullptr) {
570 buf_appendf(&entry->name, "(");
571 }
572 switch (ptr_len) {
573 case PtrLenSingle:
574 buf_appendf(&entry->name, "*");
575 break;
576 case PtrLenUnknown:
577 buf_appendf(&entry->name, "[*");
578 break;
579 case PtrLenC:
580 assert(sentinel == nullptr);
581 buf_appendf(&entry->name, "[*c]");
582 break;
583 }
584 if (sentinel != nullptr) {
585 buf_appendf(&entry->name, ":");
586 render_const_value(g, &entry->name, sentinel);
589587 }
588 switch (ptr_len) {
589 case PtrLenSingle:
590 case PtrLenC:
591 break;
592 case PtrLenUnknown:
593 buf_appendf(&entry->name, "]");
594 break;
595 }
596
590597
591598 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
592599 if (type_has_bits(child_type)) {
......@@ -615,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
615622 entry->data.pointer.allow_zero = allow_zero;
616623 entry->data.pointer.vector_index = vector_index;
617624 entry->data.pointer.inferred_struct_field = inferred_struct_field;
625 entry->data.pointer.sentinel = sentinel;
626
627 append_ptr_type_attrs(&entry->name, entry);
618628
619629 if (parent_pointer) {
620630 *parent_pointer = entry;
......@@ -629,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
629639 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
630640{
631641 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,
632 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr);
642 byte_alignment, bit_offset_in_host, host_int_bytes, allow_zero, VECTOR_INDEX_NONE, nullptr, nullptr);
633643}
634644
635645ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
636646 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,
637 VECTOR_INDEX_NONE, nullptr);
647 VECTOR_INDEX_NONE, nullptr, nullptr);
638648}
639649
640650ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {
......@@ -750,11 +760,13 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
750760 return entry;
751761}
752762
753ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
763ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel) {
754764 TypeId type_id = {};
755765 type_id.id = ZigTypeIdArray;
766 type_id.data.array.codegen = g;
756767 type_id.data.array.child_type = child_type;
757768 type_id.data.array.size = array_size;
769 type_id.data.array.sentinel = sentinel;
758770 auto existing_entry = g->type_table.maybe_get(type_id);
759771 if (existing_entry) {
760772 return existing_entry->value;
......@@ -765,14 +777,27 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
765777 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
766778
767779 buf_resize(&entry->name, 0);
768 buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
780 buf_appendf(&entry->name, "[%" ZIG_PRI_u64, array_size);
781 if (sentinel != nullptr) {
782 buf_appendf(&entry->name, ":");
783 render_const_value(g, &entry->name, sentinel);
784 }
785 buf_appendf(&entry->name, "]%s", buf_ptr(&child_type->name));
786
787 size_t full_array_size;
788 if (array_size == 0) {
789 full_array_size = 0;
790 } else {
791 full_array_size = array_size + ((sentinel != nullptr) ? 1 : 0);
792 }
769793
770 entry->size_in_bits = child_type->size_in_bits * array_size;
794 entry->size_in_bits = child_type->size_in_bits * full_array_size;
771795 entry->abi_align = child_type->abi_align;
772 entry->abi_size = child_type->abi_size * array_size;
796 entry->abi_size = child_type->abi_size * full_array_size;
773797
774798 entry->data.array.child_type = child_type;
775799 entry->data.array.len = array_size;
800 entry->data.array.sentinel = sentinel;
776801
777802 g->type_table.put(type_id, entry);
778803 return entry;
......@@ -789,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
789814
790815 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
791816
792 // replace the & with [] to go from a ptr type name to a slice type name
793817 buf_resize(&entry->name, 0);
794 size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3;
795 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);
818 buf_appendf(&entry->name, "[");
819 if (ptr_type->data.pointer.sentinel != nullptr) {
820 buf_appendf(&entry->name, ":");
821 render_const_value(g, &entry->name, ptr_type->data.pointer.sentinel);
822 }
823 buf_appendf(&entry->name, "]");
824 append_ptr_type_attrs(&entry->name, ptr_type);
796825
797826 unsigned element_count = 2;
798827 Buf *ptr_field_name = buf_create_from_str("ptr");
......@@ -832,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
832861 entry->data.structure.fields[slice_len_index]->gen_index = 0;
833862 }
834863
835 ZigType *child_type = ptr_type->data.pointer.child_type;
836 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
837 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
838 {
839 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
840 PtrLenUnknown, 0, 0, 0, false);
841 ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type);
842
843 entry->size_in_bits = peer_slice_type->size_in_bits;
844 entry->abi_size = peer_slice_type->abi_size;
845 entry->abi_align = peer_slice_type->abi_align;
846
847 *parent_pointer = entry;
848 return entry;
849 }
850
851864 if (type_has_bits(ptr_type)) {
852865 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
853866 entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;
......@@ -1150,6 +1163,10 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *
11501163Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
11511164 if (type_val->special != ConstValSpecialLazy) {
11521165 assert(type_val->special == ConstValSpecialStatic);
1166 if (type_val->data.x_type == g->builtin_types.entry_var) {
1167 *is_opaque_type = false;
1168 return ErrorNone;
1169 }
11531170 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
11541171 return ErrorNone;
11551172 }
......@@ -3638,6 +3655,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
36383655 case NodeTypeEnumLiteral:
36393656 case NodeTypeAnyFrameType:
36403657 case NodeTypeErrorSetField:
3658 case NodeTypeVarFieldType:
36413659 zig_unreachable();
36423660 }
36433661}
......@@ -5041,7 +5059,6 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
50415059 hash_val += (uint32_t)1764906839;
50425060 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
50435061 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
5044 hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492;
50455062 return hash_val;
50465063 case ConstPtrSpecialBaseStruct:
50475064 hash_val += (uint32_t)3518317043;
......@@ -5545,8 +5562,23 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
55455562 zig_unreachable();
55465563}
55475564
5565ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
5566 auto entry = g->one_possible_values.maybe_get(type_entry);
5567 if (entry != nullptr) {
5568 return entry->value;
5569 }
5570 ConstExprValue *result = create_const_vals(1);
5571 result->type = type_entry;
5572 result->special = ConstValSpecialStatic;
5573 g->one_possible_values.put(type_entry, result);
5574 return result;
5575}
5576
55485577ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
55495578 Error err;
5579 if (ty == g->builtin_types.entry_var) {
5580 return ReqCompTimeYes;
5581 }
55505582 switch (ty->id) {
55515583 case ZigTypeIdInvalid:
55525584 zig_unreachable();
......@@ -5612,52 +5644,26 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
56125644 return;
56135645 }
56145646
5615 const_val->special = ConstValSpecialStatic;
5616 const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str));
5617 const_val->data.x_array.special = ConstArraySpecialBuf;
5618 const_val->data.x_array.data.s_buf = str;
5619
5620 g->string_literals_table.put(str, const_val);
5621}
5622
5623ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
5624 ConstExprValue *const_val = create_const_vals(1);
5625 init_const_str_lit(g, const_val, str);
5626 return const_val;
5627}
5628
5629void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
56305647 // first we build the underlying array
5631 size_t len_with_null = buf_len(str) + 1;
56325648 ConstExprValue *array_val = create_const_vals(1);
56335649 array_val->special = ConstValSpecialStatic;
5634 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);
5635 // TODO buf optimization
5636 array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);
5637 for (size_t i = 0; i < buf_len(str); i += 1) {
5638 ConstExprValue *this_char = &array_val->data.x_array.data.s_none.elements[i];
5639 this_char->special = ConstValSpecialStatic;
5640 this_char->type = g->builtin_types.entry_u8;
5641 bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
5642 }
5643 ConstExprValue *null_char = &array_val->data.x_array.data.s_none.elements[len_with_null - 1];
5644 null_char->special = ConstValSpecialStatic;
5645 null_char->type = g->builtin_types.entry_u8;
5646 bigint_init_unsigned(&null_char->data.x_bigint, 0);
5650 array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), &g->const_zero_byte);
5651 array_val->data.x_array.special = ConstArraySpecialBuf;
5652 array_val->data.x_array.data.s_buf = str;
56475653
56485654 // then make the pointer point to it
56495655 const_val->special = ConstValSpecialStatic;
5650 // TODO make this `[*]null u8` instead of `[*]u8`
5651 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
5652 PtrLenUnknown, 0, 0, 0, false);
5653 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
5654 const_val->data.x_ptr.data.base_array.array_val = array_val;
5655 const_val->data.x_ptr.data.base_array.elem_index = 0;
5656 const_val->data.x_ptr.data.base_array.is_cstr = true;
5656 const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
5657 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
5658 const_val->data.x_ptr.special = ConstPtrSpecialRef;
5659 const_val->data.x_ptr.data.ref.pointee = array_val;
5660
5661 g->string_literals_table.put(str, const_val);
56575662}
5658ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
5663
5664ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
56595665 ConstExprValue *const_val = create_const_vals(1);
5660 init_const_c_str_lit(g, const_val, str);
5666 init_const_str_lit(g, const_val, str);
56615667 return const_val;
56625668}
56635669
......@@ -5707,6 +5713,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {
57075713 return const_val;
57085714}
57095715
5716void init_const_null(ConstExprValue *const_val, ZigType *type) {
5717 const_val->special = ConstValSpecialStatic;
5718 const_val->type = type;
5719 const_val->data.x_optional = nullptr;
5720}
5721
5722ConstExprValue *create_const_null(ZigType *type) {
5723 ConstExprValue *const_val = create_const_vals(1);
5724 init_const_null(const_val, type);
5725 return const_val;
5726}
5727
57105728void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {
57115729 const_val->special = ConstValSpecialStatic;
57125730 const_val->type = type;
......@@ -6069,7 +6087,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
60696087
60706088 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
60716089 fields.append({"@instruction_addresses",
6072 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
6090 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
60736091 }
60746092
60756093 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),
......@@ -6277,7 +6295,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
62776295 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
62786296 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
62796297 fields.append({"@instruction_addresses",
6280 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count), 0});
6298 get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr), 0});
62816299 }
62826300
62836301 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
......@@ -6441,8 +6459,6 @@ bool ir_get_var_is_comptime(ZigVar *var) {
64416459bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
64426460 if (a->data.x_ptr.special != b->data.x_ptr.special)
64436461 return false;
6444 if (a->data.x_ptr.mut != b->data.x_ptr.mut)
6445 return false;
64466462 switch (a->data.x_ptr.special) {
64476463 case ConstPtrSpecialInvalid:
64486464 zig_unreachable();
......@@ -6459,8 +6475,6 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
64596475 }
64606476 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
64616477 return false;
6462 if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr)
6463 return false;
64646478 return true;
64656479 case ConstPtrSpecialBaseStruct:
64666480 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val &&
......@@ -6536,9 +6550,19 @@ static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprVal
65366550}
65376551
65386552bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
6539 assert(a->type->id == b->type->id);
6553 if (a->type->id != b->type->id) return false;
65406554 assert(a->special == ConstValSpecialStatic);
65416555 assert(b->special == ConstValSpecialStatic);
6556 if (a->type == b->type) {
6557 switch (type_has_one_possible_value(g, a->type)) {
6558 case OnePossibleValueInvalid:
6559 zig_unreachable();
6560 case OnePossibleValueNo:
6561 break;
6562 case OnePossibleValueYes:
6563 return true;
6564 }
6565 }
65426566 switch (a->type->id) {
65436567 case ZigTypeIdOpaque:
65446568 zig_unreachable();
......@@ -6704,15 +6728,10 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val
67046728 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
67056729 return;
67066730 case ConstPtrSpecialBaseArray:
6707 if (const_val->data.x_ptr.data.base_array.is_cstr) {
6708 buf_appendf(buf, "*(c str lit)");
6709 return;
6710 } else {
6711 buf_appendf(buf, "*");
6712 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
6713 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
6714 return;
6715 }
6731 buf_appendf(buf, "*");
6732 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
6733 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
6734 return;
67166735 case ConstPtrSpecialHardCodedAddr:
67176736 buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
67186737 const_val->data.x_ptr.data.hard_coded_addr.addr);
......@@ -7032,17 +7051,19 @@ uint32_t type_id_hash(TypeId x) {
70327051 return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
70337052 case ZigTypeIdPointer:
70347053 return hash_ptr(x.data.pointer.child_type) +
7035 ((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
7054 (uint32_t)x.data.pointer.ptr_len * 1120226602u +
70367055 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
70377056 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
70387057 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
70397058 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
70407059 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
70417060 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +
7042 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
7061 (((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881) *
7062 (x.data.pointer.sentinel ? hash_const_val(x.data.pointer.sentinel) : (uint32_t)2955491856);
70437063 case ZigTypeIdArray:
7044 return hash_ptr(x.data.array.child_type) +
7045 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968);
7064 return hash_ptr(x.data.array.child_type) *
7065 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968) *
7066 (x.data.array.sentinel ? hash_const_val(x.data.array.sentinel) : (uint32_t)1927201585);
70467067 case ZigTypeIdInt:
70477068 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
70487069 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
......@@ -7093,6 +7114,11 @@ bool type_id_eql(TypeId a, TypeId b) {
70937114 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
70947115 a.data.pointer.vector_index == b.data.pointer.vector_index &&
70957116 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&
7117 (
7118 a.data.pointer.sentinel == b.data.pointer.sentinel ||
7119 (a.data.pointer.sentinel != nullptr && b.data.pointer.sentinel != nullptr &&
7120 const_values_equal(a.data.pointer.codegen, a.data.pointer.sentinel, b.data.pointer.sentinel))
7121 ) &&
70967122 (
70977123 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||
70987124 (a.data.pointer.inferred_struct_field != nullptr &&
......@@ -7104,7 +7130,12 @@ bool type_id_eql(TypeId a, TypeId b) {
71047130 );
71057131 case ZigTypeIdArray:
71067132 return a.data.array.child_type == b.data.array.child_type &&
7107 a.data.array.size == b.data.array.size;
7133 a.data.array.size == b.data.array.size &&
7134 (
7135 a.data.array.sentinel == b.data.array.sentinel ||
7136 (a.data.array.sentinel != nullptr && b.data.array.sentinel != nullptr &&
7137 const_values_equal(a.data.array.codegen, a.data.array.sentinel, b.data.array.sentinel))
7138 );
71087139 case ZigTypeIdInt:
71097140 return a.data.integer.is_signed == b.data.integer.is_signed &&
71107141 a.data.integer.bit_count == b.data.integer.bit_count;
......@@ -7761,7 +7792,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
77617792
77627793 bool done = false;
77637794 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
7764 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
7795 ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero ||
7796 ptr_type->data.pointer.sentinel != nullptr)
77657797 {
77667798 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
77677799 PtrLenUnknown, 0, 0, 0, false);
......@@ -7780,7 +7812,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
77807812 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;
77817813 assert(child_ptr_type->id == ZigTypeIdPointer);
77827814 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
7783 child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
7815 child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero ||
7816 child_ptr_type->data.pointer.sentinel != nullptr)
77847817 {
77857818 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
77867819 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
......@@ -8290,7 +8323,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
82908323 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
82918324 if (padding_bytes > 0) {
82928325 ZigType *u8_type = get_int_type(g, false, 8);
8293 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
8326 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
82948327 LLVMTypeRef union_element_types[] = {
82958328 most_aligned_union_member->type_entry->llvm_type,
82968329 get_llvm_type(g, padding_array),
......@@ -8324,7 +8357,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
83248357 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
83258358 } else {
83268359 ZigType *u8_type = get_int_type(g, false, 8);
8327 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes);
8360 ZigType *padding_array = get_array_type(g, u8_type, padding_bytes, nullptr);
83288361 LLVMTypeRef union_element_types[] = {
83298362 get_llvm_type(g, most_aligned_union_member->type_entry),
83308363 get_llvm_type(g, padding_array),
......@@ -8405,19 +8438,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
84058438 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
84068439 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
84078440 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||
8408 type->data.pointer.vector_index != VECTOR_INDEX_NONE)
8441 type->data.pointer.vector_index != VECTOR_INDEX_NONE || type->data.pointer.sentinel != nullptr)
84098442 {
84108443 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
84118444 ZigType *peer_type;
84128445 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
84138446 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
84148447 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8415 VECTOR_INDEX_NONE, nullptr);
8448 VECTOR_INDEX_NONE, nullptr, nullptr);
84168449 } else {
84178450 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
84188451 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
84198452 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,
8420 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);
8453 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
84218454 }
84228455 type->llvm_type = get_llvm_type(g, peer_type);
84238456 type->llvm_di_type = get_llvm_di_type(g, peer_type);
......@@ -8646,14 +8679,16 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
86468679
86478680 ZigType *elem_type = type->data.array.child_type;
86488681
8682 uint64_t extra_len_from_sentinel = (type->data.array.sentinel != nullptr) ? 1 : 0;
8683 uint64_t full_len = type->data.array.len + extra_len_from_sentinel;
86498684 // TODO https://github.com/ziglang/zig/issues/1424
8650 type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)type->data.array.len);
8685 type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
86518686
86528687 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
86538688 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
86548689
86558690 type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
8656 debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len);
8691 debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)full_len);
86578692}
86588693
86598694static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
......@@ -9143,3 +9178,11 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
91439178 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
91449179 return ErrorNone;
91459180}
9181
9182
9183void IrExecutable::src() {
9184 IrExecutable *it;
9185 for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
9186 it->source_node->src();
9187 }
9188}
src/analyze.hpp+7-6
......@@ -24,7 +24,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
2424ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
2525 bool is_const, bool is_volatile, PtrLen ptr_len,
2626 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,
27 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field);
27 bool allow_zero, uint32_t vector_index, InferredStructField *inferred_struct_field,
28 ConstExprValue *sentinel);
2829uint64_t type_size(CodeGen *g, ZigType *type_entry);
2930uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
3031ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);
......@@ -33,7 +34,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
3334ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
3435ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
3536ZigType *get_optional_type(CodeGen *g, ZigType *child_type);
36ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size);
37ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel);
3738ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
3839ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
3940 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);
......@@ -126,9 +127,6 @@ ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
126127void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
127128ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
128129
129void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
130ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
131
132130void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
133131ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);
134132
......@@ -176,6 +174,9 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
176174void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
177175ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);
178176
177void init_const_null(ConstExprValue *const_val, ZigType *type);
178ConstExprValue *create_const_null(ZigType *type);
179
179180ConstExprValue *create_const_vals(size_t count);
180181ConstExprValue **alloc_const_vals_ptrs(size_t count);
181182ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count);
......@@ -275,5 +276,5 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,
275276 ZigType *var_type, const char *name_hint);
276277Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
277278 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
278
279ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
279280#endif
src/ast_render.cpp+8-5
......@@ -147,9 +147,9 @@ static const char *token_to_ptr_len_str(Token *tok) {
147147 case TokenIdStar:
148148 case TokenIdStarStar:
149149 return "*";
150 case TokenIdBracketStarBracket:
150 case TokenIdLBracket:
151151 return "[*]";
152 case TokenIdBracketStarCBracket:
152 case TokenIdSymbol:
153153 return "[*c]";
154154 default:
155155 zig_unreachable();
......@@ -268,6 +268,8 @@ static const char *node_type_str(NodeType node_type) {
268268 return "EnumLiteral";
269269 case NodeTypeErrorSetField:
270270 return "ErrorSetField";
271 case NodeTypeVarFieldType:
272 return "VarFieldType";
271273 }
272274 zig_unreachable();
273275}
......@@ -619,9 +621,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
619621 break;
620622 case NodeTypeStringLiteral:
621623 {
622 if (node->data.string_literal.c) {
623 fprintf(ar->f, "c");
624 }
625624 Buf tmp_buf = BUF_INIT;
626625 string_literal_escape(node->data.string_literal.buf, &tmp_buf);
627626 fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));
......@@ -1187,6 +1186,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
11871186 fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
11881187 break;
11891188 }
1189 case NodeTypeVarFieldType: {
1190 fprintf(ar->f, "var");
1191 break;
1192 }
11901193 case NodeTypeParamDecl:
11911194 case NodeTypeTestDecl:
11921195 case NodeTypeStructField:
src/codegen.cpp+48-27
......@@ -949,7 +949,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
949949 if (!val->global_refs->llvm_global) {
950950
951951 Buf *buf_msg = panic_msg_buf(msg_id);
952 ConstExprValue *array_val = create_const_str_lit(g, buf_msg);
952 ConstExprValue *array_val = create_const_str_lit(g, buf_msg)->data.x_ptr.data.ref.pointee;
953953 init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);
954954
955955 render_const_val(g, val, "");
......@@ -2784,14 +2784,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
27842784 IrInstruction *op1 = bin_op_instruction->op1;
27852785 IrInstruction *op2 = bin_op_instruction->op2;
27862786
2787 assert(op1->value.type == op2->value.type || op_id == IrBinOpBitShiftLeftLossy ||
2788 op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
2789 op_id == IrBinOpBitShiftRightExact ||
2790 (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
2791 (op1->value.type->id == ZigTypeIdPointer &&
2792 (op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
2793 op1->value.type->data.pointer.ptr_len != PtrLenSingle)
2794 );
27952787 ZigType *operand_type = op1->value.type;
27962788 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
27972789
......@@ -2848,7 +2840,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
28482840 AddSubMulMul;
28492841
28502842 if (scalar_type->id == ZigTypeIdPointer) {
2851 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
28522843 LLVMValueRef subscript_value;
28532844 if (operand_type->id == ZigTypeIdVector)
28542845 zig_panic("TODO: Implement vector operations on pointers.");
......@@ -3077,7 +3068,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
30773068 case CastOpNumLitToConcrete:
30783069 zig_unreachable();
30793070 case CastOpNoop:
3080 return expr_val;
3071 if (actual_type->id == ZigTypeIdPointer && wanted_type->id == ZigTypeIdPointer &&
3072 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
3073 wanted_type->data.pointer.child_type->id == ZigTypeIdArray)
3074 {
3075 return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
3076 } else {
3077 return expr_val;
3078 }
30813079 case CastOpIntToFloat:
30823080 assert(actual_type->id == ZigTypeIdInt);
30833081 if (actual_type->data.integral.is_signed) {
......@@ -3709,8 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37093707 array_type = array_type->data.pointer.child_type;
37103708 }
37113709 if (safety_check_on) {
3712 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
3713 array_type->data.array.len, false);
3710 uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
3711 uint64_t full_len = array_type->data.array.len + extra_len_from_sentinel;
3712 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
37143713 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
37153714 }
37163715 if (array_ptr_type->data.pointer.host_int_bytes != 0) {
......@@ -3753,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37533752 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
37543753 assert(array_type->data.structure.is_slice);
37553754
3756 ZigType *ptr_type = instruction->base.value.type;
3755 ZigType *ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
37573756 if (!type_has_bits(ptr_type)) {
37583757 if (safety_check_on) {
37593758 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
......@@ -3770,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
37703769 assert(len_index != SIZE_MAX);
37713770 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
37723771 LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");
3773 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, len);
3772 LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT;
3773 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len);
37743774 }
37753775
37763776 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;
......@@ -6637,11 +6637,20 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
66376637 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
66386638 assert(array_const_val->type->id == ZigTypeIdArray);
66396639 if (!type_has_bits(array_const_val->type)) {
6640 // make this a null pointer
6641 ZigType *usize = g->builtin_types.entry_usize;
6642 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6643 get_llvm_type(g, const_val->type));
6644 return const_val->global_refs->llvm_value;
6640 if (array_const_val->type->data.array.sentinel != nullptr) {
6641 ConstExprValue *pointee = array_const_val->type->data.array.sentinel;
6642 render_const_val(g, pointee, "");
6643 render_const_val_global(g, pointee, "");
6644 const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global,
6645 get_llvm_type(g, const_val->type));
6646 return const_val->global_refs->llvm_value;
6647 } else {
6648 // make this a null pointer
6649 ZigType *usize = g->builtin_types.entry_usize;
6650 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
6651 get_llvm_type(g, const_val->type));
6652 return const_val->global_refs->llvm_value;
6653 }
66456654 }
66466655 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
66476656 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
......@@ -6955,7 +6964,9 @@ check: switch (const_val->special) {
69556964 case ConstArraySpecialUndef:
69566965 return LLVMGetUndef(get_llvm_type(g, type_entry));
69576966 case ConstArraySpecialNone: {
6958 LLVMValueRef *values = allocate<LLVMValueRef>(len);
6967 uint64_t extra_len_from_sentinel = (type_entry->data.array.sentinel != nullptr) ? 1 : 0;
6968 uint64_t full_len = len + extra_len_from_sentinel;
6969 LLVMValueRef *values = allocate<LLVMValueRef>(full_len);
69596970 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
69606971 bool make_unnamed_struct = false;
69616972 for (uint64_t i = 0; i < len; i += 1) {
......@@ -6964,15 +6975,19 @@ check: switch (const_val->special) {
69646975 values[i] = val;
69656976 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
69666977 }
6978 if (type_entry->data.array.sentinel != nullptr) {
6979 values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
6980 }
69676981 if (make_unnamed_struct) {
6968 return LLVMConstStruct(values, len, true);
6982 return LLVMConstStruct(values, full_len, true);
69696983 } else {
6970 return LLVMConstArray(element_type_ref, values, (unsigned)len);
6984 return LLVMConstArray(element_type_ref, values, (unsigned)full_len);
69716985 }
69726986 }
69736987 case ConstArraySpecialBuf: {
69746988 Buf *buf = const_val->data.x_array.data.s_buf;
6975 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
6989 return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
6990 type_entry->data.array.sentinel == nullptr);
69766991 }
69776992 }
69786993 zig_unreachable();
......@@ -7465,7 +7480,7 @@ static void do_code_gen(CodeGen *g) {
74657480 !is_async && !have_err_ret_trace_arg;
74667481 LLVMValueRef err_ret_array_val = nullptr;
74677482 if (have_err_ret_trace_stack) {
7468 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count);
7483 ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count, nullptr);
74697484 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
74707485
74717486 (void)get_llvm_type(g, get_stack_trace_type(g));
......@@ -8628,6 +8643,11 @@ static void init(CodeGen *g) {
86288643 g->const_void_val.type = g->builtin_types.entry_void;
86298644 g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);
86308645
8646 g->const_zero_byte.special = ConstValSpecialStatic;
8647 g->const_zero_byte.type = g->builtin_types.entry_u8;
8648 g->const_zero_byte.global_refs = allocate<ConstGlobalRefs>(1);
8649 bigint_init_unsigned(&g->const_zero_byte.data.x_bigint, 0);
8650
86318651 {
86328652 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);
86338653 for (size_t i = 0; i < PanicMsgIdCount; i += 1) {
......@@ -9067,7 +9087,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
90679087 zig_unreachable();
90689088
90699089 ConstExprValue *test_fn_array = create_const_vals(1);
9070 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length);
9090 test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length, nullptr);
90719091 test_fn_array->special = ConstValSpecialStatic;
90729092 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);
90739093
......@@ -9092,7 +9112,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
90929112 this_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
90939113
90949114 ConstExprValue *name_field = this_val->data.x_struct.fields[0];
9095 ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name);
9115 ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
90969116 init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true);
90979117
90989118 ConstExprValue *fn_field = this_val->data.x_struct.fields[1];
......@@ -10415,6 +10435,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
1041510435 g->external_prototypes.init(8);
1041610436 g->string_literals_table.init(16);
1041710437 g->type_info_cache.init(32);
10438 g->one_possible_values.init(32);
1041810439 g->is_test_build = is_test_build;
1041910440 g->is_single_threaded = false;
1042010441 buf_resize(&g->global_asm, 0);
src/ir.cpp+843-253
......@@ -66,6 +66,11 @@ enum ConstCastResultId {
6666 ConstCastResultIdUnresolvedInferredErrSet,
6767 ConstCastResultIdAsyncAllocatorType,
6868 ConstCastResultIdBadAllowsZero,
69 ConstCastResultIdArrayChild,
70 ConstCastResultIdSentinelArrays,
71 ConstCastResultIdPtrLens,
72 ConstCastResultIdCV,
73 ConstCastResultIdPtrSentinel,
6974};
7075
7176struct ConstCastOnly;
......@@ -87,7 +92,11 @@ struct ConstCastErrUnionErrSetMismatch;
8792struct ConstCastErrUnionPayloadMismatch;
8893struct ConstCastErrSetMismatch;
8994struct ConstCastTypeMismatch;
95struct ConstCastArrayMismatch;
9096struct ConstCastBadAllowsZero;
97struct ConstCastBadNullTermArrays;
98struct ConstCastBadCV;
99struct ConstCastPtrSentinel;
91100
92101struct ConstCastOnly {
93102 ConstCastResultId id;
......@@ -99,11 +108,15 @@ struct ConstCastOnly {
99108 ConstCastErrUnionPayloadMismatch *error_union_payload;
100109 ConstCastErrUnionErrSetMismatch *error_union_error_set;
101110 ConstCastTypeMismatch *type_mismatch;
111 ConstCastArrayMismatch *array_mismatch;
102112 ConstCastOnly *return_type;
103113 ConstCastOnly *null_wrap_ptr_child;
104114 ConstCastArg fn_arg;
105115 ConstCastArgNoAlias arg_no_alias;
106116 ConstCastBadAllowsZero *bad_allows_zero;
117 ConstCastBadNullTermArrays *sentinel_arrays;
118 ConstCastBadCV *bad_cv;
119 ConstCastPtrSentinel *bad_ptr_sentinel;
107120 } data;
108121};
109122
......@@ -130,6 +143,12 @@ struct ConstCastSliceMismatch {
130143 ZigType *actual_child;
131144};
132145
146struct ConstCastArrayMismatch {
147 ConstCastOnly child;
148 ZigType *wanted_child;
149 ZigType *actual_child;
150};
151
133152struct ConstCastErrUnionErrSetMismatch {
134153 ConstCastOnly child;
135154 ZigType *wanted_err_set;
......@@ -151,11 +170,28 @@ struct ConstCastBadAllowsZero {
151170 ZigType *actual_type;
152171};
153172
173struct ConstCastBadNullTermArrays {
174 ConstCastOnly child;
175 ZigType *wanted_type;
176 ZigType *actual_type;
177};
178
179struct ConstCastBadCV {
180 ZigType *wanted_type;
181 ZigType *actual_type;
182};
183
184struct ConstCastPtrSentinel {
185 ZigType *wanted_type;
186 ZigType *actual_type;
187};
154188
155189static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
156190static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
157191 ResultLoc *result_loc);
158192static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);
193static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr,
194 IrInstruction *value, ZigType *expected_type);
159195static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
160196 ResultLoc *result_loc);
161197static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);
......@@ -217,10 +253,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
217253 case OnePossibleValueInvalid:
218254 zig_unreachable();
219255 case OnePossibleValueYes:
220 result = create_const_vals(1);
221 result->type = const_val->type->data.pointer.child_type;
222 result->special = ConstValSpecialStatic;
223 return result;
256 return get_the_one_possible_value(g, const_val->type->data.pointer.child_type);
224257 case OnePossibleValueNo:
225258 break;
226259 }
......@@ -233,8 +266,12 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
233266 break;
234267 case ConstPtrSpecialBaseArray: {
235268 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
236 expand_undef_array(g, array_val);
237 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
269 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
270 result = array_val->type->data.array.sentinel;
271 } else {
272 expand_undef_array(g, array_val);
273 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
274 }
238275 break;
239276 }
240277 case ConstPtrSpecialBaseStruct: {
......@@ -282,20 +319,20 @@ static bool slice_is_const(ZigType *type) {
282319
283320// This function returns true when you can change the type of a ConstExprValue and the
284321// value remains meaningful.
285static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
286 if (a == b)
322static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
323 if (expected == actual)
287324 return true;
288325
289 if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
326 if (get_codegen_ptr_type(expected) != nullptr && get_codegen_ptr_type(actual) != nullptr)
290327 return true;
291328
292 if (is_opt_err_set(a) && is_opt_err_set(b))
329 if (is_opt_err_set(expected) && is_opt_err_set(actual))
293330 return true;
294331
295 if (a->id != b->id)
332 if (expected->id != actual->id)
296333 return false;
297334
298 switch (a->id) {
335 switch (expected->id) {
299336 case ZigTypeIdInvalid:
300337 case ZigTypeIdUnreachable:
301338 zig_unreachable();
......@@ -314,12 +351,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
314351 case ZigTypeIdAnyFrame:
315352 return true;
316353 case ZigTypeIdFloat:
317 return a->data.floating.bit_count == b->data.floating.bit_count;
354 return expected->data.floating.bit_count == actual->data.floating.bit_count;
318355 case ZigTypeIdInt:
319 return a->data.integral.is_signed == b->data.integral.is_signed;
356 return expected->data.integral.is_signed == actual->data.integral.is_signed;
320357 case ZigTypeIdStruct:
321 return is_slice(a) && is_slice(b);
322 case ZigTypeIdArray:
358 return is_slice(expected) && is_slice(actual);
323359 case ZigTypeIdOptional:
324360 case ZigTypeIdErrorUnion:
325361 case ZigTypeIdEnum:
......@@ -329,6 +365,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
329365 case ZigTypeIdVector:
330366 case ZigTypeIdFnFrame:
331367 return false;
368 case ZigTypeIdArray:
369 return expected->data.array.len == actual->data.array.len &&
370 expected->data.array.child_type == actual->data.array.child_type &&
371 (expected->data.array.sentinel == nullptr || (actual->data.array.sentinel != nullptr &&
372 const_values_equal(codegen, expected->data.array.sentinel, actual->data.array.sentinel)));
332373 }
333374 zig_unreachable();
334375}
......@@ -1299,12 +1340,6 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo
12991340 return instruction;
13001341}
13011342
1302static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {
1303 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
1304 init_const_c_str_lit(irb->codegen, &const_instruction->base.value, str);
1305 return &const_instruction->base;
1306}
1307
13081343static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
13091344 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
13101345{
......@@ -1544,9 +1579,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_
15441579
15451580static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
15461581 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,
1547 IrInstruction *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
1582 IrInstruction *sentinel, IrInstruction *align_value,
1583 uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero)
15481584{
15491585 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
1586 ptr_type_of_instruction->sentinel = sentinel;
15501587 ptr_type_of_instruction->align_value = align_value;
15511588 ptr_type_of_instruction->child_type = child_type;
15521589 ptr_type_of_instruction->is_const = is_const;
......@@ -1556,6 +1593,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
15561593 ptr_type_of_instruction->host_int_bytes = host_int_bytes;
15571594 ptr_type_of_instruction->is_allow_zero = is_allow_zero;
15581595
1596 if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block);
15591597 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
15601598 ir_ref_instruction(child_type, irb->current_basic_block);
15611599
......@@ -1772,13 +1810,15 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN
17721810}
17731811
17741812static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,
1775 IrInstruction *child_type)
1813 IrInstruction *sentinel, IrInstruction *child_type)
17761814{
17771815 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);
17781816 instruction->size = size;
1817 instruction->sentinel = sentinel;
17791818 instruction->child_type = child_type;
17801819
17811820 ir_ref_instruction(size, irb->current_basic_block);
1821 if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block);
17821822 ir_ref_instruction(child_type, irb->current_basic_block);
17831823
17841824 return &instruction->base;
......@@ -1794,18 +1834,22 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo
17941834
17951835 return &instruction->base;
17961836}
1837
17971838static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1798 IrInstruction *child_type, bool is_const, bool is_volatile, IrInstruction *align_value, bool is_allow_zero)
1839 IrInstruction *child_type, bool is_const, bool is_volatile,
1840 IrInstruction *sentinel, IrInstruction *align_value, bool is_allow_zero)
17991841{
18001842 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);
18011843 instruction->is_const = is_const;
18021844 instruction->is_volatile = is_volatile;
18031845 instruction->child_type = child_type;
1846 instruction->sentinel = sentinel;
18041847 instruction->align_value = align_value;
18051848 instruction->is_allow_zero = is_allow_zero;
18061849
1850 if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block);
1851 if (align_value != nullptr) ir_ref_instruction(align_value, irb->current_basic_block);
18071852 ir_ref_instruction(child_type, irb->current_basic_block);
1808 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
18091853
18101854 return &instruction->base;
18111855}
......@@ -6032,9 +6076,9 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {
60326076 case TokenIdStar:
60336077 case TokenIdStarStar:
60346078 return PtrLenSingle;
6035 case TokenIdBracketStarBracket:
6079 case TokenIdLBracket:
60366080 return PtrLenUnknown;
6037 case TokenIdBracketStarCBracket:
6081 case TokenIdSymbol:
60386082 return PtrLenC;
60396083 default:
60406084 zig_unreachable();
......@@ -6043,13 +6087,25 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {
60436087
60446088static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
60456089 assert(node->type == NodeTypePointerType);
6090
60466091 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
6092
60476093 bool is_const = node->data.pointer_type.is_const;
60486094 bool is_volatile = node->data.pointer_type.is_volatile;
60496095 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;
6096 AstNode *sentinel_expr = node->data.pointer_type.sentinel;
60506097 AstNode *expr_node = node->data.pointer_type.op_expr;
60516098 AstNode *align_expr = node->data.pointer_type.align_expr;
60526099
6100 IrInstruction *sentinel;
6101 if (sentinel_expr != nullptr) {
6102 sentinel = ir_gen_node(irb, sentinel_expr, scope);
6103 if (sentinel == irb->codegen->invalid_instruction)
6104 return sentinel;
6105 } else {
6106 sentinel = nullptr;
6107 }
6108
60536109 IrInstruction *align_value;
60546110 if (align_expr != nullptr) {
60556111 align_value = ir_gen_node(irb, align_expr, scope);
......@@ -6094,7 +6150,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
60946150 }
60956151
60966152 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,
6097 ptr_len, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
6153 ptr_len, sentinel, align_value, bit_offset_start, host_int_bytes, is_allow_zero);
60986154}
60996155
61006156static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,
......@@ -6198,13 +6254,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
61986254 buf_sprintf("initializing array with struct syntax"));
61996255 return irb->codegen->invalid_instruction;
62006256 }
6257 IrInstruction *sentinel;
6258 if (container_init_expr->type->data.inferred_array_type.sentinel != nullptr) {
6259 sentinel = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.sentinel, scope);
6260 if (sentinel == irb->codegen->invalid_instruction)
6261 return sentinel;
6262 } else {
6263 sentinel = nullptr;
6264 }
6265
62016266 IrInstruction *elem_type = ir_gen_node(irb,
62026267 container_init_expr->type->data.inferred_array_type.child_type, scope);
62036268 if (elem_type == irb->codegen->invalid_instruction)
62046269 return elem_type;
62056270 size_t item_count = container_init_expr->entries.length;
62066271 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
6207 container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
6272 container_type = ir_build_array_type(irb, scope, node, item_count_inst, sentinel, elem_type);
62086273 } else {
62096274 container_type = ir_gen_node(irb, container_init_expr->type, scope);
62106275 if (container_type == irb->codegen->invalid_instruction)
......@@ -6917,11 +6982,7 @@ static IrInstruction *ir_gen_enum_literal(IrBuilder *irb, Scope *scope, AstNode
69176982static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
69186983 assert(node->type == NodeTypeStringLiteral);
69196984
6920 if (node->data.string_literal.c) {
6921 return ir_build_const_c_str_lit(irb, scope, node, node->data.string_literal.buf);
6922 } else {
6923 return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf);
6924 }
6985 return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf);
69256986}
69266987
69276988static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *node) {
......@@ -6932,9 +6993,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
69326993 bool is_const = node->data.array_type.is_const;
69336994 bool is_volatile = node->data.array_type.is_volatile;
69346995 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;
6996 AstNode *sentinel_expr = node->data.array_type.sentinel;
69356997 AstNode *align_expr = node->data.array_type.align_expr;
69366998
69376999 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);
7000
7001 IrInstruction *sentinel;
7002 if (sentinel_expr != nullptr) {
7003 sentinel = ir_gen_node(irb, sentinel_expr, comptime_scope);
7004 if (sentinel == irb->codegen->invalid_instruction)
7005 return sentinel;
7006 } else {
7007 sentinel = nullptr;
7008 }
7009
69387010 if (size_node) {
69397011 if (is_const) {
69407012 add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type"));
......@@ -6961,7 +7033,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
69617033 if (child_type == irb->codegen->invalid_instruction)
69627034 return child_type;
69637035
6964 return ir_build_array_type(irb, scope, node, size_value, child_type);
7036 return ir_build_array_type(irb, scope, node, size_value, sentinel, child_type);
69657037 } else {
69667038 IrInstruction *align_value;
69677039 if (align_expr != nullptr) {
......@@ -6976,7 +7048,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
69767048 if (child_type == irb->codegen->invalid_instruction)
69777049 return child_type;
69787050
6979 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, align_value, is_allow_zero);
7051 return ir_build_slice_type(irb, scope, node, child_type, is_const, is_volatile, sentinel,
7052 align_value, is_allow_zero);
69807053 }
69817054}
69827055
......@@ -8486,6 +8559,9 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
84868559 add_node_error(irb->codegen, node,
84878560 buf_sprintf("inferred array size invalid here"));
84888561 return irb->codegen->invalid_instruction;
8562 case NodeTypeVarFieldType:
8563 return ir_lval_wrap(irb, scope,
8564 ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var), lval, result_loc);
84898565 }
84908566 zig_unreachable();
84918567}
......@@ -8645,7 +8721,18 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
86458721 assert(val != nullptr);
86468722 assert(const_val->type->id == ZigTypeIdPointer);
86478723 ZigType *expected_type = const_val->type->data.pointer.child_type;
8648 if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
8724 if (expected_type == codegen->builtin_types.entry_var) {
8725 return val;
8726 }
8727 switch (type_has_one_possible_value(codegen, expected_type)) {
8728 case OnePossibleValueInvalid:
8729 return nullptr;
8730 case OnePossibleValueNo:
8731 break;
8732 case OnePossibleValueYes:
8733 return get_the_one_possible_value(codegen, expected_type);
8734 }
8735 if (!types_have_same_zig_comptime_repr(codegen, expected_type, val->type)) {
86498736 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
86508737 return nullptr;
86518738 return const_ptr_pointee_unchecked(codegen, const_val);
......@@ -9793,6 +9880,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
97939880 // alignment can be decreased
97949881 // bit offset attributes must match exactly
97959882 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
9883 // sentinel-terminated pointers can coerce into PtrLenUnknown
97969884 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
97979885 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
97989886 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
......@@ -9804,6 +9892,35 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
98049892 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
98059893 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
98069894 if (wanted_opt_or_ptr && actual_opt_or_ptr) {
9895 bool ok_null_term_ptrs =
9896 wanted_ptr_type->data.pointer.sentinel == nullptr ||
9897 (actual_ptr_type->data.pointer.sentinel != nullptr &&
9898 const_values_equal(ira->codegen, wanted_ptr_type->data.pointer.sentinel,
9899 actual_ptr_type->data.pointer.sentinel));
9900 if (!ok_null_term_ptrs) {
9901 result.id = ConstCastResultIdPtrSentinel;
9902 result.data.bad_ptr_sentinel = allocate_nonzero<ConstCastPtrSentinel>(1);
9903 result.data.bad_ptr_sentinel->wanted_type = wanted_ptr_type;
9904 result.data.bad_ptr_sentinel->actual_type = actual_ptr_type;
9905 return result;
9906 }
9907 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
9908 if (!(ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr)) {
9909 result.id = ConstCastResultIdPtrLens;
9910 return result;
9911 }
9912
9913 bool ok_cv_qualifiers =
9914 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
9915 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile);
9916 if (!ok_cv_qualifiers) {
9917 result.id = ConstCastResultIdCV;
9918 result.data.bad_cv = allocate_nonzero<ConstCastBadCV>(1);
9919 result.data.bad_cv->wanted_type = wanted_ptr_type;
9920 result.data.bad_cv->actual_type = actual_ptr_type;
9921 return result;
9922 }
9923
98079924 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
98089925 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
98099926 if (child.id == ConstCastResultIdInvalid)
......@@ -9842,11 +9959,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
98429959 result.id = ConstCastResultIdInvalid;
98439960 return result;
98449961 }
9845 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
9846 if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
9847 type_has_bits(wanted_type) == type_has_bits(actual_type) &&
9848 (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
9849 (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
9962 if (type_has_bits(wanted_type) == type_has_bits(actual_type) &&
98509963 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
98519964 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
98529965 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
......@@ -9855,6 +9968,36 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
98559968 }
98569969 }
98579970
9971 // arrays
9972 if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdArray &&
9973 wanted_type->data.array.len == actual_type->data.array.len)
9974 {
9975 ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.array.child_type,
9976 actual_type->data.array.child_type, source_node, wanted_is_mutable);
9977 if (child.id == ConstCastResultIdInvalid)
9978 return child;
9979 if (child.id != ConstCastResultIdOk) {
9980 result.id = ConstCastResultIdArrayChild;
9981 result.data.array_mismatch = allocate_nonzero<ConstCastArrayMismatch>(1);
9982 result.data.array_mismatch->child = child;
9983 result.data.array_mismatch->wanted_child = wanted_type->data.array.child_type;
9984 result.data.array_mismatch->actual_child = actual_type->data.array.child_type;
9985 return result;
9986 }
9987 bool ok_null_terminated = (wanted_type->data.array.sentinel == nullptr) ||
9988 (actual_type->data.array.sentinel != nullptr &&
9989 const_values_equal(ira->codegen, wanted_type->data.array.sentinel, actual_type->data.array.sentinel));
9990 if (!ok_null_terminated) {
9991 result.id = ConstCastResultIdSentinelArrays;
9992 result.data.sentinel_arrays = allocate_nonzero<ConstCastBadNullTermArrays>(1);
9993 result.data.sentinel_arrays->child = child;
9994 result.data.sentinel_arrays->wanted_type = wanted_type;
9995 result.data.sentinel_arrays->actual_type = actual_type;
9996 return result;
9997 }
9998 return result;
9999 }
10000
985810001 // slice const
985910002 if (is_slice(wanted_type) && is_slice(actual_type)) {
986010003 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry;
......@@ -10615,6 +10758,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1061510758 // *[N]T to []T
1061610759 // *[N]T to E![]T
1061710760 if (cur_type->id == ZigTypeIdPointer &&
10761 cur_type->data.pointer.ptr_len == PtrLenSingle &&
1061810762 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
1061910763 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||
1062010764 is_slice(prev_type)))
......@@ -10623,7 +10767,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1062310767 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
1062410768 prev_type->data.error_union.payload_type : prev_type;
1062510769 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
10626 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
10770 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
10771 !cur_type->data.pointer.is_const) &&
1062710772 types_match_const_cast_only(ira,
1062810773 slice_ptr_type->data.pointer.child_type,
1062910774 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
......@@ -10637,6 +10782,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1063710782 // *[N]T to E![]T
1063810783 if (prev_type->id == ZigTypeIdPointer &&
1063910784 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10785 prev_type->data.pointer.ptr_len == PtrLenSingle &&
1064010786 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
1064110787 is_slice(cur_type)))
1064210788 {
......@@ -10644,7 +10790,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1064410790 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
1064510791 cur_type->data.error_union.payload_type : cur_type;
1064610792 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
10647 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0) &&
10793 if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
10794 !prev_type->data.pointer.is_const) &&
1064810795 types_match_const_cast_only(ira,
1064910796 slice_ptr_type->data.pointer.child_type,
1065010797 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)
......@@ -10667,6 +10814,50 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1066710814 continue;
1066810815 }
1066910816
10817
10818 // *[N]T and *[M]T
10819 if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
10820 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
10821 prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
10822 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10823 (cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
10824 prev_type->data.pointer.child_type->data.array.len == 0) &&
10825 (
10826 prev_type->data.pointer.child_type->data.array.sentinel == nullptr ||
10827 (cur_type->data.pointer.child_type->data.array.sentinel != nullptr &&
10828 const_values_equal(ira->codegen, prev_type->data.pointer.child_type->data.array.sentinel,
10829 cur_type->data.pointer.child_type->data.array.sentinel))
10830 ) &&
10831 types_match_const_cast_only(ira,
10832 cur_type->data.pointer.child_type->data.array.child_type,
10833 prev_type->data.pointer.child_type->data.array.child_type,
10834 source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
10835 {
10836 prev_inst = cur_inst;
10837 convert_to_const_slice = true;
10838 continue;
10839 }
10840 if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
10841 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10842 cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
10843 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
10844 (prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
10845 cur_type->data.pointer.child_type->data.array.len == 0) &&
10846 (
10847 cur_type->data.pointer.child_type->data.array.sentinel == nullptr ||
10848 (prev_type->data.pointer.child_type->data.array.sentinel != nullptr &&
10849 const_values_equal(ira->codegen, cur_type->data.pointer.child_type->data.array.sentinel,
10850 prev_type->data.pointer.child_type->data.array.sentinel))
10851 ) &&
10852 types_match_const_cast_only(ira,
10853 prev_type->data.pointer.child_type->data.array.child_type,
10854 cur_type->data.pointer.child_type->data.array.child_type,
10855 source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
10856 {
10857 convert_to_const_slice = true;
10858 continue;
10859 }
10860
1067010861 // [N]T to []T
1067110862 if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&
1067210863 (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||
......@@ -10715,16 +10906,34 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
1071510906 free(errors);
1071610907
1071710908 if (convert_to_const_slice) {
10718 assert(prev_inst->value.type->id == ZigTypeIdArray);
10719 ZigType *ptr_type = get_pointer_to_type_extra(
10720 ira->codegen, prev_inst->value.type->data.array.child_type,
10721 true, false, PtrLenUnknown,
10722 0, 0, 0, false);
10723 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
10724 if (err_set_type != nullptr) {
10725 return get_error_union_type(ira->codegen, err_set_type, slice_type);
10909 if (prev_inst->value.type->id == ZigTypeIdArray) {
10910 ZigType *ptr_type = get_pointer_to_type_extra(
10911 ira->codegen, prev_inst->value.type->data.array.child_type,
10912 true, false, PtrLenUnknown,
10913 0, 0, 0, false);
10914 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
10915 if (err_set_type != nullptr) {
10916 return get_error_union_type(ira->codegen, err_set_type, slice_type);
10917 } else {
10918 return slice_type;
10919 }
10920 } else if (prev_inst->value.type->id == ZigTypeIdPointer) {
10921 ZigType *array_type = prev_inst->value.type->data.pointer.child_type;
10922 src_assert(array_type->id == ZigTypeIdArray, source_node);
10923 ZigType *ptr_type = get_pointer_to_type_extra2(
10924 ira->codegen, array_type->data.array.child_type,
10925 prev_inst->value.type->data.pointer.is_const, false,
10926 PtrLenUnknown,
10927 0, 0, 0, false,
10928 VECTOR_INDEX_NONE, nullptr, array_type->data.array.sentinel);
10929 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
10930 if (err_set_type != nullptr) {
10931 return get_error_union_type(ira->codegen, err_set_type, slice_type);
10932 } else {
10933 return slice_type;
10934 }
1072610935 } else {
10727 return slice_type;
10936 zig_unreachable();
1072810937 }
1072910938 } else if (err_set_type != nullptr) {
1073010939 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
......@@ -10945,7 +11154,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
1094511154 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
1094611155 result->value.data.x_ptr.data.base_array.array_val = pointee;
1094711156 result->value.data.x_ptr.data.base_array.elem_index = 0;
10948 result->value.data.x_ptr.data.base_array.is_cstr = false;
1094911157 return result;
1095011158 }
1095111159 }
......@@ -10957,31 +11165,31 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
1095711165}
1095811166
1095911167static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
10960 IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
11168 IrInstruction *array_ptr, ZigType *wanted_type, ResultLoc *result_loc)
1096111169{
1096211170 Error err;
1096311171
10964 if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
11172 if ((err = type_resolve(ira->codegen, array_ptr->value.type->data.pointer.child_type,
1096511173 ResolveStatusAlignmentKnown)))
1096611174 {
1096711175 return ira->codegen->invalid_instruction;
1096811176 }
1096911177
10970 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
11178 wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, array_ptr->value.type));
1097111179
10972 if (instr_is_comptime(value)) {
10973 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
11180 if (instr_is_comptime(array_ptr)) {
11181 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &array_ptr->value, source_instr->source_node);
1097411182 if (pointee == nullptr)
1097511183 return ira->codegen->invalid_instruction;
1097611184 if (pointee->special != ConstValSpecialRuntime) {
10977 assert(value->value.type->id == ZigTypeIdPointer);
10978 ZigType *array_type = value->value.type->data.pointer.child_type;
11185 assert(array_ptr->value.type->id == ZigTypeIdPointer);
11186 ZigType *array_type = array_ptr->value.type->data.pointer.child_type;
1097911187 assert(is_slice(wanted_type));
1098011188 bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
1098111189
1098211190 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
1098311191 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
10984 result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = value->value.data.x_ptr.mut;
11192 result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr->value.data.x_ptr.mut;
1098511193 result->value.type = wanted_type;
1098611194 return result;
1098711195 }
......@@ -10993,7 +11201,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
1099311201 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
1099411202 return result_loc_inst;
1099511203 }
10996 return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, value, result_loc_inst);
11204 return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst);
1099711205}
1099811206
1099911207static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
......@@ -11524,7 +11732,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
1152411732 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
1152511733 source_instr->scope, source_instr->source_node);
1152611734 const_instruction->base.value.special = ConstValSpecialStatic;
11527 if (types_have_same_zig_comptime_repr(wanted_type, payload_type)) {
11735 if (types_have_same_zig_comptime_repr(ira->codegen, wanted_type, payload_type)) {
1152811736 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
1152911737 } else {
1153011738 const_instruction->base.value.data.x_optional = val;
......@@ -12442,6 +12650,55 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1244212650 }
1244312651 break;
1244412652 }
12653 case ConstCastResultIdPtrLens: {
12654 add_error_note(ira->codegen, parent_msg, source_node,
12655 buf_sprintf("pointer length mismatch"));
12656 break;
12657 }
12658 case ConstCastResultIdPtrSentinel: {
12659 ZigType *actual_type = cast_result->data.bad_ptr_sentinel->actual_type;
12660 ZigType *wanted_type = cast_result->data.bad_ptr_sentinel->wanted_type;
12661 {
12662 Buf *txt_msg = buf_sprintf("destination pointer requires a terminating '");
12663 render_const_value(ira->codegen, txt_msg, wanted_type->data.pointer.sentinel);
12664 buf_appendf(txt_msg, "' sentinel");
12665 if (actual_type->data.pointer.sentinel != nullptr) {
12666 buf_appendf(txt_msg, ", but source pointer has a terminating '");
12667 render_const_value(ira->codegen, txt_msg, actual_type->data.pointer.sentinel);
12668 buf_appendf(txt_msg, "' sentinel");
12669 }
12670 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
12671 }
12672 break;
12673 }
12674 case ConstCastResultIdSentinelArrays: {
12675 ZigType *actual_type = cast_result->data.sentinel_arrays->actual_type;
12676 ZigType *wanted_type = cast_result->data.sentinel_arrays->wanted_type;
12677 Buf *txt_msg = buf_sprintf("destination array requires a terminating '");
12678 render_const_value(ira->codegen, txt_msg, wanted_type->data.array.sentinel);
12679 buf_appendf(txt_msg, "' sentinel");
12680 if (actual_type->data.array.sentinel != nullptr) {
12681 buf_appendf(txt_msg, ", but source array has a terminating '");
12682 render_const_value(ira->codegen, txt_msg, actual_type->data.array.sentinel);
12683 buf_appendf(txt_msg, "' sentinel");
12684 }
12685 add_error_note(ira->codegen, parent_msg, source_node, txt_msg);
12686 break;
12687 }
12688 case ConstCastResultIdCV: {
12689 ZigType *wanted_type = cast_result->data.bad_cv->wanted_type;
12690 ZigType *actual_type = cast_result->data.bad_cv->actual_type;
12691 bool ok_const = !actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const;
12692 bool ok_volatile = !actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile;
12693 if (!ok_const) {
12694 add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards const qualifier"));
12695 } else if (!ok_volatile) {
12696 add_error_note(ira->codegen, parent_msg, source_node, buf_sprintf("cast discards volatile qualifier"));
12697 } else {
12698 zig_unreachable();
12699 }
12700 break;
12701 }
1244512702 case ConstCastResultIdFnIsGeneric:
1244612703 add_error_note(ira->codegen, parent_msg, source_node,
1244712704 buf_sprintf("only one of the functions is generic"));
......@@ -12458,6 +12715,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
1245812715 case ConstCastResultIdFnArgNoAlias: // TODO
1245912716 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
1246012717 case ConstCastResultIdAsyncAllocatorType: // TODO
12718 case ConstCastResultIdArrayChild: // TODO
1246112719 break;
1246212720 }
1246312721}
......@@ -12584,8 +12842,55 @@ static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstr
1258412842 return ira->codegen->invalid_instruction;
1258512843}
1258612844
12845// Add a compile error and return ErrorSemanticAnalyzeFail if the pointer alignment does not work,
12846// otherwise return ErrorNone. Does not emit any instructions.
12847// Assumes that the pointer types have element types with the same ABI alignment. Avoids resolving the
12848// pointer types' alignments if both of the pointer types are ABI aligned.
12849static Error ir_cast_ptr_align(IrAnalyze *ira, IrInstruction *source_instr, ZigType *dest_ptr_type,
12850 ZigType *src_ptr_type, AstNode *src_source_node)
12851{
12852 Error err;
12853
12854 ir_assert(dest_ptr_type->id == ZigTypeIdPointer, source_instr);
12855 ir_assert(src_ptr_type->id == ZigTypeIdPointer, source_instr);
12856
12857 if (dest_ptr_type->data.pointer.explicit_alignment == 0 &&
12858 src_ptr_type->data.pointer.explicit_alignment == 0)
12859 {
12860 return ErrorNone;
12861 }
12862
12863 if ((err = type_resolve(ira->codegen, dest_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
12864 return ErrorSemanticAnalyzeFail;
12865
12866 if ((err = type_resolve(ira->codegen, src_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
12867 return ErrorSemanticAnalyzeFail;
12868
12869 uint32_t wanted_align = get_ptr_align(ira->codegen, dest_ptr_type);
12870 uint32_t actual_align = get_ptr_align(ira->codegen, src_ptr_type);
12871 if (wanted_align > actual_align) {
12872 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
12873 add_error_note(ira->codegen, msg, src_source_node,
12874 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&src_ptr_type->name), actual_align));
12875 add_error_note(ira->codegen, msg, source_instr->source_node,
12876 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&dest_ptr_type->name), wanted_align));
12877 return ErrorSemanticAnalyzeFail;
12878 }
12879
12880 return ErrorNone;
12881}
12882
12883static IrInstruction *ir_analyze_struct_value_field_value(IrAnalyze *ira, IrInstruction *source_instr,
12884 IrInstruction *struct_operand, TypeStructField *field)
12885{
12886 IrInstruction *struct_ptr = ir_get_ref(ira, source_instr, struct_operand, true, false);
12887 IrInstruction *field_ptr = ir_analyze_struct_field_ptr(ira, source_instr, field, struct_ptr,
12888 struct_operand->value.type, false);
12889 return ir_get_deref(ira, source_instr, field_ptr, nullptr);
12890}
12891
1258712892static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
12588 ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)
12893 ZigType *wanted_type, IrInstruction *value)
1258912894{
1259012895 Error err;
1259112896 ZigType *actual_type = value->value.type;
......@@ -12631,12 +12936,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1263112936 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
1263212937 false).id == ConstCastResultIdOk)
1263312938 {
12634 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
12939 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, nullptr);
1263512940 } else if (actual_type->id == ZigTypeIdComptimeInt ||
1263612941 actual_type->id == ZigTypeIdComptimeFloat)
1263712942 {
1263812943 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {
12639 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, result_loc);
12944 return ir_analyze_optional_wrap(ira, source_instr, value, wanted_type, nullptr);
1264012945 } else {
1264112946 return ira->codegen->invalid_instruction;
1264212947 }
......@@ -12660,7 +12965,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1266012965 wanted_child_type);
1266112966 if (type_is_invalid(cast1->value.type))
1266212967 return ira->codegen->invalid_instruction;
12663 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, result_loc);
12968 return ir_analyze_optional_wrap(ira, source_instr, cast1, wanted_type, nullptr);
1266412969 }
1266512970 }
1266612971 }
......@@ -12670,12 +12975,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1267012975 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
1267112976 source_node, false).id == ConstCastResultIdOk)
1267212977 {
12673 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
12978 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, nullptr);
1267412979 } else if (actual_type->id == ZigTypeIdComptimeInt ||
1267512980 actual_type->id == ZigTypeIdComptimeFloat)
1267612981 {
1267712982 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {
12678 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, result_loc);
12983 return ir_analyze_err_wrap_payload(ira, source_instr, value, wanted_type, nullptr);
1267912984 } else {
1268012985 return ira->codegen->invalid_instruction;
1268112986 }
......@@ -12693,11 +12998,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1269312998 actual_type->id == ZigTypeIdComptimeInt ||
1269412999 actual_type->id == ZigTypeIdComptimeFloat)
1269513000 {
12696 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
13001 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
1269713002 if (type_is_invalid(cast1->value.type))
1269813003 return ira->codegen->invalid_instruction;
1269913004
12700 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
13005 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1270113006 if (type_is_invalid(cast2->value.type))
1270213007 return ira->codegen->invalid_instruction;
1270313008
......@@ -12770,7 +13075,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1277013075 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
1277113076 }
1277213077
12773
1277413078 // cast from [N]T to []const T
1277513079 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
1277613080 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
......@@ -12780,7 +13084,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1278013084 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1278113085 source_node, false).id == ConstCastResultIdOk)
1278213086 {
12783 return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type, result_loc);
13087 return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type, nullptr);
1278413088 }
1278513089 }
1278613090
......@@ -12797,11 +13101,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1279713101 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1279813102 source_node, false).id == ConstCastResultIdOk)
1279913103 {
12800 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value, nullptr);
13104 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
1280113105 if (type_is_invalid(cast1->value.type))
1280213106 return ira->codegen->invalid_instruction;
1280313107
12804 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
13108 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1280513109 if (type_is_invalid(cast2->value.type))
1280613110 return ira->codegen->invalid_instruction;
1280713111
......@@ -12809,23 +13113,50 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1280913113 }
1281013114 }
1281113115
12812 // *[N]T to [*]T and [*c]T
12813 if (wanted_type->id == ZigTypeIdPointer &&
12814 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
13116 // *[N]T to ?[]const T
13117 if (wanted_type->id == ZigTypeIdOptional &&
13118 is_slice(wanted_type->data.maybe.child_type) &&
1281513119 actual_type->id == ZigTypeIdPointer &&
1281613120 actual_type->data.pointer.ptr_len == PtrLenSingle &&
1281713121 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
1281813122 {
12819 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
13123 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value);
13124 if (type_is_invalid(cast1->value.type))
1282013125 return ira->codegen->invalid_instruction;
12821 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
13126
13127 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
13128 if (type_is_invalid(cast2->value.type))
1282213129 return ira->codegen->invalid_instruction;
12823 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
12824 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
12825 actual_type->data.pointer.child_type->data.array.child_type, source_node,
12826 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
13130
13131 return cast2;
13132 }
13133
13134 // *[N]T to [*]T and [*c]T
13135 if (wanted_type->id == ZigTypeIdPointer &&
13136 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
13137 actual_type->id == ZigTypeIdPointer &&
13138 actual_type->data.pointer.ptr_len == PtrLenSingle &&
13139 actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
13140 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
13141 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
13142 {
13143 ZigType *actual_array_type = actual_type->data.pointer.child_type;
13144 if (wanted_type->data.pointer.sentinel == nullptr ||
13145 (actual_array_type->data.array.sentinel != nullptr &&
13146 const_values_equal(ira->codegen, wanted_type->data.pointer.sentinel,
13147 actual_array_type->data.array.sentinel)))
1282713148 {
12828 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
13149 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
13150 return ira->codegen->invalid_instruction;
13151 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
13152 return ira->codegen->invalid_instruction;
13153 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
13154 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
13155 actual_type->data.pointer.child_type->data.array.child_type, source_node,
13156 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
13157 {
13158 return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
13159 }
1282913160 }
1283013161 }
1283113162
......@@ -12870,17 +13201,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1287013201 }
1287113202 if (ok_align) {
1287213203 if (wanted_type->id == ZigTypeIdErrorUnion) {
12873 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value, nullptr);
13204 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, slice_type, value);
1287413205 if (type_is_invalid(cast1->value.type))
1287513206 return ira->codegen->invalid_instruction;
1287613207
12877 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
13208 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1287813209 if (type_is_invalid(cast2->value.type))
1287913210 return ira->codegen->invalid_instruction;
1288013211
1288113212 return cast2;
1288213213 } else {
12883 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc);
13214 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, nullptr);
1288413215 }
1288513216 }
1288613217 }
......@@ -12921,7 +13252,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1292113252 ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
1292213253 }
1292313254 if (ok_align) {
12924 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, result_loc);
13255 return ir_resolve_ptr_of_array_to_slice(ira, source_instr, value, slice_type, nullptr);
1292513256 }
1292613257 }
1292713258 }
......@@ -12977,11 +13308,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1297713308 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
1297813309 source_node, false).id == ConstCastResultIdOk)
1297913310 {
12980 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value, nullptr);
13311 IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.error_union.payload_type, value);
1298113312 if (type_is_invalid(cast1->value.type))
1298213313 return ira->codegen->invalid_instruction;
1298313314
12984 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
13315 IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1);
1298513316 if (type_is_invalid(cast2->value.type))
1298613317 return ira->codegen->invalid_instruction;
1298713318
......@@ -12993,7 +13324,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1299313324 if (wanted_type->id == ZigTypeIdErrorUnion &&
1299413325 actual_type->id == ZigTypeIdErrorSet)
1299513326 {
12996 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type, result_loc);
13327 return ir_analyze_err_wrap_code(ira, source_instr, value, wanted_type, nullptr);
1299713328 }
1299813329
1299913330 // cast from typed number to integer or float literal.
......@@ -13019,7 +13350,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1301913350 if (result == ira->codegen->invalid_instruction)
1302013351 return result;
1302113352
13022 return ir_analyze_optional_wrap(ira, result, value, wanted_type, result_loc);
13353 return ir_analyze_optional_wrap(ira, result, value, wanted_type, nullptr);
1302313354 }
1302413355
1302513356 // cast from enum literal to error union when payload is an enum
......@@ -13030,7 +13361,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1303013361 if (result == ira->codegen->invalid_instruction)
1303113362 return result;
1303213363
13033 return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, result_loc);
13364 return ir_analyze_err_wrap_payload(ira, result, value, wanted_type, nullptr);
1303413365 }
1303513366
1303613367 // cast from union to the enum type of the union
......@@ -13060,35 +13391,39 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1306013391 types_match_const_cast_only(ira, array_type->data.array.child_type,
1306113392 actual_type->data.pointer.child_type, source_node,
1306213393 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&
13063 // This should be the job of `types_match_const_cast_only`
13064 // but `types_match_const_cast_only` only gets info for child_types
13065 ((wanted_type->data.pointer.is_const && actual_type->data.pointer.is_const) ||
13066 !actual_type->data.pointer.is_const))
13394 // `types_match_const_cast_only` only gets info for child_types
13395 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
13396 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
1306713397 {
13068 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type,
13069 ResolveStatusAlignmentKnown)))
13070 {
13071 return ira->codegen->invalid_instruction;
13072 }
13073 if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type,
13074 ResolveStatusAlignmentKnown)))
13075 {
13076 return ira->codegen->invalid_instruction;
13077 }
13078 uint32_t wanted_align = get_ptr_align(ira->codegen, wanted_type);
13079 uint32_t actual_align = get_ptr_align(ira->codegen, actual_type);
13080 if (wanted_align > actual_align) {
13081 ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
13082 add_error_note(ira->codegen, msg, value->source_node,
13083 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), actual_align));
13084 add_error_note(ira->codegen, msg, source_instr->source_node,
13085 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), wanted_align));
13398 if ((err = ir_cast_ptr_align(ira, source_instr, wanted_type, actual_type, value->source_node)))
1308613399 return ira->codegen->invalid_instruction;
13087 }
13400
1308813401 return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
1308913402 }
1309013403 }
1309113404
13405 // [:x]T to [*:x]T
13406 // [:x]T to [*c]T
13407 if (wanted_type->id == ZigTypeIdPointer && is_slice(actual_type) &&
13408 ((wanted_type->data.pointer.ptr_len == PtrLenUnknown && wanted_type->data.pointer.sentinel != nullptr) ||
13409 wanted_type->data.pointer.ptr_len == PtrLenC))
13410 {
13411 ZigType *slice_ptr_type = resolve_struct_field_type(ira->codegen,
13412 actual_type->data.structure.fields[slice_ptr_index]);
13413 if (types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
13414 slice_ptr_type->data.pointer.child_type, source_node,
13415 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&
13416 (slice_ptr_type->data.pointer.sentinel != nullptr &&
13417 (wanted_type->data.pointer.ptr_len == PtrLenC ||
13418 const_values_equal(ira->codegen, wanted_type->data.pointer.sentinel,
13419 slice_ptr_type->data.pointer.sentinel))))
13420 {
13421 TypeStructField *ptr_field = actual_type->data.structure.fields[slice_ptr_index];
13422 IrInstruction *slice_ptr = ir_analyze_struct_value_field_value(ira, source_instr, value, ptr_field);
13423 return ir_implicit_cast2(ira, source_instr, slice_ptr, wanted_type);
13424 }
13425 }
13426
1309213427 // cast from *T and [*]T to *c_void and ?*c_void
1309313428 // but don't do it if the actual type is a double pointer
1309413429 if (is_pointery_and_elem_is_not_pointery(actual_type)) {
......@@ -13127,7 +13462,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1312713462 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
1312813463 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
1312913464 {
13130 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type, result_loc);
13465 return ir_analyze_vector_to_array(ira, source_instr, value, wanted_type, nullptr);
1313113466 }
1313213467
1313313468 // cast from [N]T to @Vector(N, T)
......@@ -13188,8 +13523,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1318813523 return ira->codegen->invalid_instruction;
1318913524}
1319013525
13191static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *source_instr,
13192 IrInstruction *value, ZigType *expected_type, ResultLoc *result_loc)
13526static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr,
13527 IrInstruction *value, ZigType *expected_type)
1319313528{
1319413529 assert(value);
1319513530 assert(value != ira->codegen->invalid_instruction);
......@@ -13203,11 +13538,11 @@ static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction
1320313538 if (value->value.type->id == ZigTypeIdUnreachable)
1320413539 return value;
1320513540
13206 return ir_analyze_cast(ira, source_instr, expected_type, value, result_loc);
13541 return ir_analyze_cast(ira, value_source_instr, expected_type, value);
1320713542}
1320813543
1320913544static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {
13210 return ir_implicit_cast_with_result(ira, value, value, expected_type, nullptr);
13545 return ir_implicit_cast2(ira, value, value, expected_type);
1321113546}
1321213547
1321313548static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
......@@ -13242,6 +13577,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1324213577 }
1324313578 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1324413579 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13580 if (child_type == ira->codegen->builtin_types.entry_var) {
13581 child_type = pointee->type;
13582 }
1324513583 if (pointee->special != ConstValSpecialRuntime) {
1324613584 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1324713585
......@@ -14519,8 +14857,6 @@ static bool ok_float_op(IrBinOp op) {
1451914857}
1452014858
1452114859static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
14522 if (lhs_type->id != ZigTypeIdPointer)
14523 return false;
1452414860 switch (op) {
1452514861 case IrBinOpAdd:
1452614862 case IrBinOpSub:
......@@ -14528,14 +14864,16 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
1452814864 default:
1452914865 return false;
1453014866 }
14867 if (lhs_type->id != ZigTypeIdPointer)
14868 return false;
1453114869 switch (lhs_type->data.pointer.ptr_len) {
1453214870 case PtrLenSingle:
14533 return false;
14871 return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;
1453414872 case PtrLenUnknown:
1453514873 case PtrLenC:
14536 break;
14874 return true;
1453714875 }
14538 return true;
14876 zig_unreachable();
1453914877}
1454014878
1454114879static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
......@@ -14797,6 +15135,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1479715135 if (!op2_val)
1479815136 return ira->codegen->invalid_instruction;
1479915137
15138 ConstExprValue *sentinel1 = nullptr;
1480015139 ConstExprValue *op1_array_val;
1480115140 size_t op1_array_index;
1480215141 size_t op1_array_end;
......@@ -14806,15 +15145,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1480615145 op1_array_val = op1_val;
1480715146 op1_array_index = 0;
1480815147 op1_array_end = op1_type->data.array.len;
15148 sentinel1 = op1_type->data.array.sentinel;
1480915149 } else if (op1_type->id == ZigTypeIdPointer &&
1481015150 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
14811 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
14812 op1_val->data.x_ptr.data.base_array.is_cstr)
15151 op1_type->data.pointer.sentinel != nullptr &&
15152 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
1481315153 {
1481415154 child_type = op1_type->data.pointer.child_type;
1481515155 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
1481615156 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
14817 op1_array_end = op1_array_val->type->data.array.len - 1;
15157 op1_array_end = op1_array_val->type->data.array.len;
15158 sentinel1 = op1_type->data.pointer.sentinel;
1481815159 } else if (is_slice(op1_type)) {
1481915160 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
1482015161 child_type = ptr_type->data.pointer.child_type;
......@@ -14824,12 +15165,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1482415165 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1482515166 ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
1482615167 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
15168 sentinel1 = ptr_type->data.pointer.sentinel;
15169 } else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle &&
15170 op1_type->data.pointer.child_type->id == ZigTypeIdArray)
15171 {
15172 ZigType *array_type = op1_type->data.pointer.child_type;
15173 child_type = array_type->data.array.child_type;
15174 op1_array_val = const_ptr_pointee(ira, ira->codegen, op1_val, op1->source_node);
15175 if (op1_array_val == nullptr)
15176 return ira->codegen->invalid_instruction;
15177 op1_array_index = 0;
15178 op1_array_end = array_type->data.array.len;
15179 sentinel1 = array_type->data.array.sentinel;
1482715180 } else {
1482815181 ir_add_error(ira, op1,
14829 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
15182 buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value.type->name)));
1483015183 return ira->codegen->invalid_instruction;
1483115184 }
1483215185
15186 ConstExprValue *sentinel2 = nullptr;
1483315187 ConstExprValue *op2_array_val;
1483415188 size_t op2_array_index;
1483515189 size_t op2_array_end;
......@@ -14839,15 +15193,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1483915193 op2_array_val = op2_val;
1484015194 op2_array_index = 0;
1484115195 op2_array_end = op2_array_val->type->data.array.len;
15196 sentinel2 = op2_type->data.array.sentinel;
1484215197 } else if (op2_type->id == ZigTypeIdPointer &&
14843 op2_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
14844 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
14845 op2_val->data.x_ptr.data.base_array.is_cstr)
15198 op2_type->data.pointer.sentinel != nullptr &&
15199 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
1484615200 {
14847 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
15201 op2_type_valid = op2_type->data.pointer.child_type == child_type;
1484815202 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
1484915203 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
14850 op2_array_end = op2_array_val->type->data.array.len - 1;
15204 op2_array_end = op2_array_val->type->data.array.len;
15205
15206 sentinel2 = op2_type->data.pointer.sentinel;
1485115207 } else if (is_slice(op2_type)) {
1485215208 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
1485315209 op2_type_valid = ptr_type->data.pointer.child_type == child_type;
......@@ -14857,6 +15213,20 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1485715213 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
1485815214 ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];
1485915215 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);
15216
15217 sentinel2 = ptr_type->data.pointer.sentinel;
15218 } else if (op2_type->id == ZigTypeIdPointer && op2_type->data.pointer.ptr_len == PtrLenSingle &&
15219 op2_type->data.pointer.child_type->id == ZigTypeIdArray)
15220 {
15221 ZigType *array_type = op2_type->data.pointer.child_type;
15222 op2_type_valid = array_type->data.array.child_type == child_type;
15223 op2_array_val = const_ptr_pointee(ira, ira->codegen, op2_val, op2->source_node);
15224 if (op2_array_val == nullptr)
15225 return ira->codegen->invalid_instruction;
15226 op2_array_index = 0;
15227 op2_array_end = array_type->data.array.len;
15228
15229 sentinel2 = array_type->data.array.sentinel;
1486015230 } else {
1486115231 ir_add_error(ira, op2,
1486215232 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
......@@ -14869,6 +15239,19 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1486915239 return ira->codegen->invalid_instruction;
1487015240 }
1487115241
15242 ConstExprValue *sentinel;
15243 if (sentinel1 != nullptr && sentinel2 != nullptr) {
15244 // When there is a sentinel mismatch, no sentinel on the result. The type system
15245 // will catch this if it is a problem.
15246 sentinel = const_values_equal(ira->codegen, sentinel1, sentinel2) ? sentinel1 : nullptr;
15247 } else if (sentinel1 != nullptr) {
15248 sentinel = sentinel1;
15249 } else if (sentinel2 != nullptr) {
15250 sentinel = sentinel2;
15251 } else {
15252 sentinel = nullptr;
15253 }
15254
1487215255 // The type of result is populated in the following if blocks
1487315256 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
1487415257 ConstExprValue *out_val = &result->value;
......@@ -14876,16 +15259,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1487615259 ConstExprValue *out_array_val;
1487715260 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
1487815261 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {
14879 result->value.type = get_array_type(ira->codegen, child_type, new_len);
15262 result->value.type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1488015263
1488115264 out_array_val = out_val;
15265 } else if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) {
15266 out_array_val = create_const_vals(1);
15267 out_array_val->special = ConstValSpecialStatic;
15268 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
15269
15270 out_val->data.x_ptr.special = ConstPtrSpecialRef;
15271 out_val->data.x_ptr.data.ref.pointee = out_array_val;
15272 out_val->type = get_pointer_to_type(ira->codegen, out_array_val->type, true);
1488215273 } else if (is_slice(op1_type) || is_slice(op2_type)) {
14883 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
14884 true, false, PtrLenUnknown, 0, 0, 0, false);
15274 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, child_type,
15275 true, false, PtrLenUnknown, 0, 0, 0, false,
15276 VECTOR_INDEX_NONE, nullptr, sentinel);
1488515277 result->value.type = get_slice_type(ira->codegen, ptr_type);
1488615278 out_array_val = create_const_vals(1);
1488715279 out_array_val->special = ConstValSpecialStatic;
14888 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);
15280 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1488915281
1489015282 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
1489115283
......@@ -14899,46 +15291,54 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
1489915291 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;
1490015292 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
1490115293 } else {
14902 new_len += 1; // null byte
14903
14904 // TODO make this `[*]null T` instead of `[*]T`
14905 result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0, false);
15294 result->value.type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown,
15295 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel);
1490615296
1490715297 out_array_val = create_const_vals(1);
1490815298 out_array_val->special = ConstValSpecialStatic;
14909 out_array_val->type = get_array_type(ira->codegen, child_type, new_len);
15299 out_array_val->type = get_array_type(ira->codegen, child_type, new_len, sentinel);
1491015300 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
14911 out_val->data.x_ptr.data.base_array.is_cstr = true;
1491215301 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
1491315302 out_val->data.x_ptr.data.base_array.elem_index = 0;
1491415303 }
1491515304
1491615305 if (op1_array_val->data.x_array.special == ConstArraySpecialUndef &&
14917 op2_array_val->data.x_array.special == ConstArraySpecialUndef) {
15306 op2_array_val->data.x_array.special == ConstArraySpecialUndef)
15307 {
1491815308 out_array_val->data.x_array.special = ConstArraySpecialUndef;
1491915309 return result;
1492015310 }
1492115311
14922 out_array_val->data.x_array.data.s_none.elements = create_const_vals(new_len);
15312 uint64_t full_len = new_len + ((sentinel != nullptr) ? 1 : 0);
15313 out_array_val->data.x_array.data.s_none.elements = create_const_vals(full_len);
1492315314 // TODO handle the buf case here for an optimization
1492415315 expand_undef_array(ira->codegen, op1_array_val);
1492515316 expand_undef_array(ira->codegen, op2_array_val);
1492615317
1492715318 size_t next_index = 0;
1492815319 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {
14929 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14930 &op1_array_val->data.x_array.data.s_none.elements[i], true);
15320 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15321 copy_const_val(elem_dest_val, &op1_array_val->data.x_array.data.s_none.elements[i], false);
15322 elem_dest_val->parent.id = ConstParentIdArray;
15323 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15324 elem_dest_val->parent.data.p_array.elem_index = next_index;
1493115325 }
1493215326 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {
14933 copy_const_val(&out_array_val->data.x_array.data.s_none.elements[next_index],
14934 &op2_array_val->data.x_array.data.s_none.elements[i], true);
14935 }
14936 if (next_index < new_len) {
14937 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];
14938 init_const_unsigned_negative(null_byte, child_type, 0, false);
15327 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15328 copy_const_val(elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i], false);
15329 elem_dest_val->parent.id = ConstParentIdArray;
15330 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15331 elem_dest_val->parent.data.p_array.elem_index = next_index;
15332 }
15333 if (next_index < full_len) {
15334 ConstExprValue *elem_dest_val = &out_array_val->data.x_array.data.s_none.elements[next_index];
15335 copy_const_val(elem_dest_val, sentinel, false);
15336 elem_dest_val->parent.id = ConstParentIdArray;
15337 elem_dest_val->parent.data.p_array.array_val = out_array_val;
15338 elem_dest_val->parent.data.p_array.elem_index = next_index;
1493915339 next_index += 1;
1494015340 }
14941 assert(next_index == new_len);
15341 assert(next_index == full_len);
1494215342
1494315343 return result;
1494415344}
......@@ -14952,20 +15352,34 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1495215352 if (type_is_invalid(op2->value.type))
1495315353 return ira->codegen->invalid_instruction;
1495415354
14955 ConstExprValue *array_val = ir_resolve_const(ira, op1, UndefBad);
14956 if (!array_val)
15355 bool want_ptr_to_array = false;
15356 ZigType *array_type;
15357 ConstExprValue *array_val;
15358 if (op1->value.type->id == ZigTypeIdArray) {
15359 array_type = op1->value.type;
15360 array_val = ir_resolve_const(ira, op1, UndefOk);
15361 if (array_val == nullptr)
15362 return ira->codegen->invalid_instruction;
15363 } else if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenSingle &&
15364 op1->value.type->data.pointer.child_type->id == ZigTypeIdArray)
15365 {
15366 array_type = op1->value.type->data.pointer.child_type;
15367 IrInstruction *array_inst = ir_get_deref(ira, op1, op1, nullptr);
15368 if (type_is_invalid(array_inst->value.type))
15369 return ira->codegen->invalid_instruction;
15370 array_val = ir_resolve_const(ira, array_inst, UndefOk);
15371 if (array_val == nullptr)
15372 return ira->codegen->invalid_instruction;
15373 want_ptr_to_array = true;
15374 } else {
15375 ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
1495715376 return ira->codegen->invalid_instruction;
15377 }
1495815378
1495915379 uint64_t mult_amt;
1496015380 if (!ir_resolve_usize(ira, op2, &mult_amt))
1496115381 return ira->codegen->invalid_instruction;
1496215382
14963 ZigType *array_type = op1->value.type;
14964 if (array_type->id != ZigTypeIdArray) {
14965 ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
14966 return ira->codegen->invalid_instruction;
14967 }
14968
1496915383 uint64_t old_array_len = array_type->data.array.len;
1497015384 uint64_t new_array_len;
1497115385
......@@ -14975,42 +15389,58 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
1497515389 }
1497615390
1497715391 ZigType *child_type = array_type->data.array.child_type;
15392 ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len,
15393 array_type->data.array.sentinel);
1497815394
14979 IrInstruction *result = ir_const(ira, &instruction->base,
14980 get_array_type(ira->codegen, child_type, new_array_len));
14981 ConstExprValue *out_val = &result->value;
14982 if (array_val->data.x_array.special == ConstArraySpecialUndef) {
14983 out_val->data.x_array.special = ConstArraySpecialUndef;
14984 return result;
14985 }
15395 IrInstruction *array_result;
15396 if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
15397 array_result = ir_const_undef(ira, &instruction->base, result_array_type);
15398 } else {
15399 array_result = ir_const(ira, &instruction->base, result_array_type);
15400 ConstExprValue *out_val = &array_result->value;
1498615401
14987 switch (type_has_one_possible_value(ira->codegen, result->value.type)) {
14988 case OnePossibleValueInvalid:
14989 return ira->codegen->invalid_instruction;
14990 case OnePossibleValueYes:
14991 return result;
14992 case OnePossibleValueNo:
14993 break;
14994 }
15402 switch (type_has_one_possible_value(ira->codegen, result_array_type)) {
15403 case OnePossibleValueInvalid:
15404 return ira->codegen->invalid_instruction;
15405 case OnePossibleValueYes:
15406 goto skip_computation;
15407 case OnePossibleValueNo:
15408 break;
15409 }
1499515410
14996 // TODO optimize the buf case
14997 expand_undef_array(ira->codegen, array_val);
14998 out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len);
15411 // TODO optimize the buf case
15412 expand_undef_array(ira->codegen, array_val);
15413 size_t extra_null_term = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
15414 out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len + extra_null_term);
1499915415
15000 uint64_t i = 0;
15001 for (uint64_t x = 0; x < mult_amt; x += 1) {
15002 for (uint64_t y = 0; y < old_array_len; y += 1) {
15416 uint64_t i = 0;
15417 for (uint64_t x = 0; x < mult_amt; x += 1) {
15418 for (uint64_t y = 0; y < old_array_len; y += 1) {
15419 ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
15420 copy_const_val(elem_dest_val, &array_val->data.x_array.data.s_none.elements[y], false);
15421 elem_dest_val->parent.id = ConstParentIdArray;
15422 elem_dest_val->parent.data.p_array.array_val = out_val;
15423 elem_dest_val->parent.data.p_array.elem_index = i;
15424 i += 1;
15425 }
15426 }
15427 assert(i == new_array_len);
15428
15429 if (array_type->data.array.sentinel != nullptr) {
1500315430 ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
15004 copy_const_val(elem_dest_val, &array_val->data.x_array.data.s_none.elements[y], false);
15431 copy_const_val(elem_dest_val, array_type->data.array.sentinel, false);
1500515432 elem_dest_val->parent.id = ConstParentIdArray;
1500615433 elem_dest_val->parent.data.p_array.array_val = out_val;
1500715434 elem_dest_val->parent.data.p_array.elem_index = i;
1500815435 i += 1;
1500915436 }
1501015437 }
15011 assert(i == new_array_len);
15012
15013 return result;
15438skip_computation:
15439 if (want_ptr_to_array) {
15440 return ir_get_ref(ira, &instruction->base, array_result, true, false);
15441 } else {
15442 return array_result;
15443 }
1501415444}
1501515445
1501615446static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
......@@ -15909,7 +16339,19 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
1590916339 if (!type_has_bits(value_type)) {
1591016340 parent_ptr_align = 0;
1591116341 }
15912 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, value_type,
16342 // If we're casting from a sentinel-terminated array to a non-sentinel-terminated array,
16343 // we actually need the result location pointer to *not* have a sentinel. Otherwise the generated
16344 // memcpy will write an extra byte to the destination, and THAT'S NO GOOD.
16345 ZigType *ptr_elem_type;
16346 if (value_type->id == ZigTypeIdArray && value_type->data.array.sentinel != nullptr &&
16347 dest_type->id == ZigTypeIdArray && dest_type->data.array.sentinel == nullptr)
16348 {
16349 ptr_elem_type = get_array_type(ira->codegen, value_type->data.array.child_type,
16350 value_type->data.array.len, nullptr);
16351 } else {
16352 ptr_elem_type = value_type;
16353 }
16354 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, ptr_elem_type,
1591316355 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
1591416356 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
1591516357
......@@ -17283,6 +17725,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1728317725 assert(out_val->type != nullptr);
1728417726
1728517727 ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
17728 src_assert(pointee->type != nullptr, source_node);
1728617729
1728717730 if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
1728817731 return ErrorSemanticAnalyzeFail;
......@@ -17293,7 +17736,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
1729317736 size_t dst_size = type_size(codegen, out_val->type);
1729417737
1729517738 if (dst_size <= src_size) {
17296 if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
17739 if (src_size == dst_size && types_have_same_zig_comptime_repr(codegen, out_val->type, pointee->type)) {
1729717740 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
1729817741 return ErrorNone;
1729917742 }
......@@ -17882,13 +18325,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi
1788218325
1788318326static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
1788418327 assert(ptr_type->id == ZigTypeIdPointer);
17885 return get_pointer_to_type_extra(g,
18328 return get_pointer_to_type_extra2(g,
1788618329 ptr_type->data.pointer.child_type,
1788718330 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1788818331 ptr_type->data.pointer.ptr_len,
1788918332 new_align,
1789018333 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,
17891 ptr_type->data.pointer.allow_zero);
18334 ptr_type->data.pointer.allow_zero,
18335 ptr_type->data.pointer.vector_index,
18336 ptr_type->data.pointer.inferred_struct_field,
18337 ptr_type->data.pointer.sentinel);
1789218338}
1789318339
1789418340static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {
......@@ -18044,6 +18490,12 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1804418490 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
1804518491 if (array_type->id == ZigTypeIdArray) {
1804618492 uint64_t array_len = array_type->data.array.len;
18493 if (index == array_len && array_type->data.array.sentinel != nullptr) {
18494 ZigType *elem_type = array_type->data.array.child_type;
18495 IrInstruction *sentinel_elem = ir_const(ira, &elem_ptr_instruction->base, elem_type);
18496 copy_const_val(&sentinel_elem->value, array_type->data.array.sentinel, false);
18497 return ir_get_ref(ira, &elem_ptr_instruction->base, sentinel_elem, true, false);
18498 }
1804718499 if (index >= array_len) {
1804818500 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1804918501 buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,
......@@ -18059,7 +18511,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1805918511 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1806018512 elem_ptr_instruction->ptr_len,
1806118513 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
18062 nullptr);
18514 nullptr, nullptr);
1806318515 } else if (return_type->data.pointer.explicit_alignment != 0) {
1806418516 // figure out the largest alignment possible
1806518517
......@@ -18166,18 +18618,37 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1816618618 case ConstPtrSpecialDiscard:
1816718619 zig_unreachable();
1816818620 case ConstPtrSpecialRef:
18169 mem_size = 1;
18170 old_size = 1;
18171 new_index = index;
18621 if (array_ptr_val->data.x_ptr.data.ref.pointee->type->id == ZigTypeIdArray) {
18622 ConstExprValue *array_val = array_ptr_val->data.x_ptr.data.ref.pointee;
18623 new_index = index;
18624 ZigType *array_type = array_val->type;
18625 mem_size = array_type->data.array.len;
18626 if (array_type->data.array.sentinel != nullptr) {
18627 mem_size += 1;
18628 }
18629 old_size = mem_size;
1817218630
18173 out_val->data.x_ptr.special = ConstPtrSpecialRef;
18174 out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
18631 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
18632 out_val->data.x_ptr.data.base_array.array_val = array_val;
18633 out_val->data.x_ptr.data.base_array.elem_index = new_index;
18634 } else {
18635 mem_size = 1;
18636 old_size = 1;
18637 new_index = index;
18638
18639 out_val->data.x_ptr.special = ConstPtrSpecialRef;
18640 out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;
18641 }
1817518642 break;
1817618643 case ConstPtrSpecialBaseArray:
1817718644 {
1817818645 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
1817918646 new_index = offset + index;
18180 mem_size = array_ptr_val->data.x_ptr.data.base_array.array_val->type->data.array.len;
18647 ZigType *array_type = array_ptr_val->data.x_ptr.data.base_array.array_val->type;
18648 mem_size = array_type->data.array.len;
18649 if (array_type->data.array.sentinel != nullptr) {
18650 mem_size += 1;
18651 }
1818118652 old_size = mem_size - offset;
1818218653
1818318654 assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
......@@ -18186,8 +18657,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1818618657 out_val->data.x_ptr.data.base_array.array_val =
1818718658 array_ptr_val->data.x_ptr.data.base_array.array_val;
1818818659 out_val->data.x_ptr.data.base_array.elem_index = new_index;
18189 out_val->data.x_ptr.data.base_array.is_cstr =
18190 array_ptr_val->data.x_ptr.data.base_array.is_cstr;
1819118660
1819218661 break;
1819318662 }
......@@ -18225,8 +18694,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1822518694 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];
1822618695 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
1822718696 ConstExprValue *out_val = &result->value;
18697 ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
1822818698 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);
18229 if (index >= slice_len) {
18699 uint64_t full_slice_len = slice_len +
18700 ((slice_ptr_type->data.pointer.sentinel != nullptr) ? 1 : 0);
18701 if (index >= full_slice_len) {
1823018702 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
1823118703 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
1823218704 index, slice_len));
......@@ -18245,14 +18717,17 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1824518717 {
1824618718 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
1824718719 uint64_t new_index = offset + index;
18248 ir_assert(new_index < ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len,
18720 if (ptr_field->data.x_ptr.data.base_array.array_val->data.x_array.special !=
18721 ConstArraySpecialBuf)
18722 {
18723 ir_assert(new_index <
18724 ptr_field->data.x_ptr.data.base_array.array_val->type->data.array.len,
1824918725 &elem_ptr_instruction->base);
18726 }
1825018727 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
1825118728 out_val->data.x_ptr.data.base_array.array_val =
1825218729 ptr_field->data.x_ptr.data.base_array.array_val;
1825318730 out_val->data.x_ptr.data.base_array.elem_index = new_index;
18254 out_val->data.x_ptr.data.base_array.is_cstr =
18255 ptr_field->data.x_ptr.data.base_array.is_cstr;
1825618731 break;
1825718732 }
1825818733 case ConstPtrSpecialBaseStruct:
......@@ -18301,7 +18776,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
1830118776 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
1830218777 elem_ptr_instruction->ptr_len,
1830318778 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,
18304 nullptr);
18779 nullptr, nullptr);
1830518780 } else {
1830618781 // runtime known element index
1830718782 switch (type_requires_comptime(ira->codegen, return_type)) {
......@@ -18505,7 +18980,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
1850518980 ZigType *elem_type = ira->codegen->builtin_types.entry_var;
1850618981 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
1850718982 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,
18508 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field);
18983 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, inferred_struct_field, nullptr);
1850918984
1851018985 if (instr_is_comptime(container_ptr)) {
1851118986 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);
......@@ -19287,6 +19762,12 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
1928719762 return ira->codegen->invalid_instruction;
1928819763 }
1928919764
19765 if (slice_type_instruction->sentinel != nullptr) {
19766 lazy_slice_type->sentinel = slice_type_instruction->sentinel->child;
19767 if (ir_resolve_const(ira, lazy_slice_type->sentinel, LazyOk) == nullptr)
19768 return ira->codegen->invalid_instruction;
19769 }
19770
1929019771 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
1929119772 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
1929219773 return ira->codegen->invalid_instruction;
......@@ -19368,6 +19849,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
1936819849 ZigType *child_type = ir_resolve_type(ira, child_type_value);
1936919850 if (type_is_invalid(child_type))
1937019851 return ira->codegen->invalid_instruction;
19852
19853 ConstExprValue *sentinel_val;
19854 if (array_type_instruction->sentinel != nullptr) {
19855 IrInstruction *uncasted_sentinel = array_type_instruction->sentinel->child;
19856 if (type_is_invalid(uncasted_sentinel->value.type))
19857 return ira->codegen->invalid_instruction;
19858 IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, child_type);
19859 if (type_is_invalid(sentinel->value.type))
19860 return ira->codegen->invalid_instruction;
19861 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
19862 if (sentinel_val == nullptr)
19863 return ira->codegen->invalid_instruction;
19864 } else {
19865 sentinel_val = nullptr;
19866 }
19867
1937119868 switch (child_type->id) {
1937219869 case ZigTypeIdInvalid: // handled above
1937319870 zig_unreachable();
......@@ -19403,7 +19900,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
1940319900 {
1940419901 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
1940519902 return ira->codegen->invalid_instruction;
19406 ZigType *result_type = get_array_type(ira->codegen, child_type, size);
19903 ZigType *result_type = get_array_type(ira->codegen, child_type, size, sentinel_val);
1940719904 return ir_const_type(ira, &array_type_instruction->base, result_type);
1940819905 }
1940919906 }
......@@ -19476,13 +19973,24 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
1947619973 return ir_analyze_test_non_null(ira, &instruction->base, value);
1947719974}
1947819975
19976static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
19977 ir_assert(ptr->value.type->id == ZigTypeIdPointer, ptr);
19978 ZigType *elem_type = ptr->value.type->data.pointer.child_type;
19979 if (elem_type != g->builtin_types.entry_var)
19980 return elem_type;
19981
19982 if (ir_resolve_lazy(g, ptr->source_node, &ptr->value))
19983 return g->builtin_types.entry_invalid;
19984
19985 assert(value_is_comptime(&ptr->value));
19986 ConstExprValue *pointee = const_ptr_pointee_unchecked(g, &ptr->value);
19987 return pointee->type;
19988}
19989
1947919990static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
1948019991 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
1948119992{
19482 ZigType *ptr_type = base_ptr->value.type;
19483 assert(ptr_type->id == ZigTypeIdPointer);
19484
19485 ZigType *type_entry = ptr_type->data.pointer.child_type;
19993 ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr);
1948619994 if (type_is_invalid(type_entry))
1948719995 return ira->codegen->invalid_instruction;
1948819996
......@@ -19520,9 +20028,10 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
1952020028
1952120029 ZigType *child_type = type_entry->data.maybe.child_type;
1952220030 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
19523 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
20031 base_ptr->value.type->data.pointer.is_const, base_ptr->value.type->data.pointer.is_volatile,
20032 PtrLenSingle, 0, 0, 0, false);
1952420033
19525 bool same_comptime_repr = types_have_same_zig_comptime_repr(type_entry, child_type);
20034 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, child_type, type_entry);
1952620035
1952720036 if (instr_is_comptime(base_ptr)) {
1952820037 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
......@@ -20479,7 +20988,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
2047920988 if (container_type->id == ZigTypeIdArray) {
2048020989 ZigType *child_type = container_type->data.array.child_type;
2048120990 if (container_type->data.array.len != elem_count) {
20482 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
20991 ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count, nullptr);
2048320992
2048420993 ir_add_error(ira, &instruction->base,
2048520994 buf_sprintf("expected %s literal, found %s literal",
......@@ -20657,7 +21166,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
2065721166 return ira->codegen->invalid_instruction;
2065821167 ErrorTableEntry *err = casted_value->value.data.x_err_set;
2065921168 if (!err->cached_error_name_val) {
20660 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);
21169 ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name)->data.x_ptr.data.ref.pointee;
2066121170 err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
2066221171 }
2066321172 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
......@@ -20686,7 +21195,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
2068621195 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
2068721196 return ira->codegen->invalid_instruction;
2068821197 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
20689 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
21198 ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
2069021199 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
2069121200 init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);
2069221201 return result;
......@@ -20966,7 +21475,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2096621475
2096721476 ConstExprValue *declaration_array = create_const_vals(1);
2096821477 declaration_array->special = ConstValSpecialStatic;
20969 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count);
21478 declaration_array->type = get_array_type(ira->codegen, type_info_declaration_type, declaration_count, nullptr);
2097021479 declaration_array->data.x_array.special = ConstArraySpecialNone;
2097121480 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);
2097221481 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);
......@@ -20991,7 +21500,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2099121500 declaration_val->type = type_info_declaration_type;
2099221501
2099321502 ConstExprValue **inner_fields = alloc_const_vals_ptrs(3);
20994 ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key);
21503 ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key)->data.x_ptr.data.ref.pointee;
2099521504 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true);
2099621505 inner_fields[1]->special = ConstValSpecialStatic;
2099721506 inner_fields[1]->type = ira->codegen->builtin_types.entry_bool;
......@@ -21094,7 +21603,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2109421603 fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
2109521604 if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {
2109621605 fn_decl_fields[6]->data.x_optional = create_const_vals(1);
21097 ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
21606 ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name)->data.x_ptr.data.ref.pointee;
2109821607 init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0,
2109921608 buf_len(fn_node->lib_name), true);
2110021609 } else {
......@@ -21111,7 +21620,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2111121620 ConstExprValue *fn_arg_name_array = create_const_vals(1);
2111221621 fn_arg_name_array->special = ConstValSpecialStatic;
2111321622 fn_arg_name_array->type = get_array_type(ira->codegen,
21114 get_slice_type(ira->codegen, u8_ptr), fn_arg_count);
21623 get_slice_type(ira->codegen, u8_ptr), fn_arg_count, nullptr);
2111521624 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
2111621625 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2111721626
......@@ -21121,7 +21630,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2112121630 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
2112221631 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
2112321632 ConstExprValue *arg_name = create_const_str_lit(ira->codegen,
21124 buf_create_from_str(arg_var->name));
21633 buf_create_from_str(arg_var->name))->data.x_ptr.data.ref.pointee;
2112521634 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true);
2112621635 fn_arg_name_val->parent.id = ConstParentIdArray;
2112721636 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
......@@ -21210,7 +21719,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
2121021719 result->special = ConstValSpecialStatic;
2121121720 result->type = type_info_pointer_type;
2121221721
21213 ConstExprValue **fields = alloc_const_vals_ptrs(6);
21722 ConstExprValue **fields = alloc_const_vals_ptrs(7);
2121421723 result->data.x_struct.fields = fields;
2121521724
2121621725 // size: Size
......@@ -21246,6 +21755,16 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
2124621755 fields[5]->special = ConstValSpecialStatic;
2124721756 fields[5]->type = ira->codegen->builtin_types.entry_bool;
2124821757 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
21758 // sentinel: var
21759 ensure_field_index(result->type, "sentinel", 6);
21760 fields[6]->special = ConstValSpecialStatic;
21761 if (attrs_type->data.pointer.sentinel != nullptr) {
21762 fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
21763 fields[6]->data.x_optional = attrs_type->data.pointer.sentinel;
21764 } else {
21765 fields[6]->type = ira->codegen->builtin_types.entry_null;
21766 fields[6]->data.x_optional = nullptr;
21767 }
2124921768
2125021769 return result;
2125121770};
......@@ -21260,7 +21779,7 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
2126021779 inner_fields[1]->special = ConstValSpecialStatic;
2126121780 inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
2126221781
21263 ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name);
21782 ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name)->data.x_ptr.data.ref.pointee;
2126421783 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true);
2126521784
2126621785 bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value);
......@@ -21353,7 +21872,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2135321872 result->special = ConstValSpecialStatic;
2135421873 result->type = ir_type_info_get_type(ira, "Array", nullptr);
2135521874
21356 ConstExprValue **fields = alloc_const_vals_ptrs(2);
21875 ConstExprValue **fields = alloc_const_vals_ptrs(3);
2135721876 result->data.x_struct.fields = fields;
2135821877
2135921878 // len: usize
......@@ -21366,7 +21885,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2136621885 fields[1]->special = ConstValSpecialStatic;
2136721886 fields[1]->type = ira->codegen->builtin_types.entry_type;
2136821887 fields[1]->data.x_type = type_entry->data.array.child_type;
21369
21888 // sentinel: var
21889 fields[2]->special = ConstValSpecialStatic;
21890 fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type);
21891 fields[2]->data.x_optional = type_entry->data.array.sentinel;
2137021892 break;
2137121893 }
2137221894 case ZigTypeIdVector: {
......@@ -21453,7 +21975,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2145321975
2145421976 ConstExprValue *enum_field_array = create_const_vals(1);
2145521977 enum_field_array->special = ConstValSpecialStatic;
21456 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count);
21978 enum_field_array->type = get_array_type(ira->codegen, type_info_enum_field_type, enum_field_count, nullptr);
2145721979 enum_field_array->data.x_array.special = ConstArraySpecialNone;
2145821980 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);
2145921981
......@@ -21501,7 +22023,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2150122023 uint32_t error_count = type_entry->data.error_set.err_count;
2150222024 ConstExprValue *error_array = create_const_vals(1);
2150322025 error_array->special = ConstValSpecialStatic;
21504 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count);
22026 error_array->type = get_array_type(ira->codegen, type_info_error_type, error_count, nullptr);
2150522027 error_array->data.x_array.special = ConstArraySpecialNone;
2150622028 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);
2150722029
......@@ -21521,7 +22043,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2152122043 if (error->cached_error_name_val != nullptr)
2152222044 name = error->cached_error_name_val;
2152322045 if (name == nullptr)
21524 name = create_const_str_lit(ira->codegen, &error->name);
22046 name = create_const_str_lit(ira->codegen, &error->name)->data.x_ptr.data.ref.pointee;
2152522047 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true);
2152622048 bigint_init_unsigned(&inner_fields[1]->data.x_bigint, error->value);
2152722049
......@@ -21597,7 +22119,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2159722119
2159822120 ConstExprValue *union_field_array = create_const_vals(1);
2159922121 union_field_array->special = ConstValSpecialStatic;
21600 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count);
22122 union_field_array->type = get_array_type(ira->codegen, type_info_union_field_type, union_field_count, nullptr);
2160122123 union_field_array->data.x_array.special = ConstArraySpecialNone;
2160222124 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);
2160322125
......@@ -21627,7 +22149,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2162722149 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
2162822150 inner_fields[2]->data.x_type = union_field->type_entry;
2162922151
21630 ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name);
22152 ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
2163122153 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
2163222154
2163322155 union_field_val->data.x_struct.fields = inner_fields;
......@@ -21677,7 +22199,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2167722199
2167822200 ConstExprValue *struct_field_array = create_const_vals(1);
2167922201 struct_field_array->special = ConstValSpecialStatic;
21680 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count);
22202 struct_field_array->type = get_array_type(ira->codegen, type_info_struct_field_type, struct_field_count, nullptr);
2168122203 struct_field_array->data.x_array.special = ConstArraySpecialNone;
2168222204 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);
2168322205
......@@ -21713,7 +22235,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2171322235 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
2171422236 inner_fields[2]->data.x_type = struct_field->type_entry;
2171522237
21716 ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name);
22238 ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
2171722239 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
2171822240
2171922241 struct_field_val->data.x_struct.fields = inner_fields;
......@@ -21780,7 +22302,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2178022302
2178122303 ConstExprValue *fn_arg_array = create_const_vals(1);
2178222304 fn_arg_array->special = ConstValSpecialStatic;
21783 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count);
22305 fn_arg_array->type = get_array_type(ira->codegen, type_info_fn_arg_type, fn_arg_count, nullptr);
2178422306 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
2178522307 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);
2178622308
......@@ -21878,6 +22400,20 @@ static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_va
2187822400 return struct_value->data.x_struct.fields[field_index];
2187922401}
2188022402
22403static Error get_const_field_sentinel(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *struct_value,
22404 const char *name, size_t field_index, ZigType *elem_type, ConstExprValue **result)
22405{
22406 ConstExprValue *field_val = get_const_field(ira, struct_value, name, field_index);
22407 IrInstruction *field_inst = ir_const(ira, source_instr, field_val->type);
22408 IrInstruction *casted_field_inst = ir_implicit_cast(ira, field_inst,
22409 get_optional_type(ira->codegen, elem_type));
22410 if (type_is_invalid(casted_field_inst->value.type))
22411 return ErrorSemanticAnalyzeFail;
22412
22413 *result = casted_field_inst->value.data.x_optional;
22414 return ErrorNone;
22415}
22416
2188122417static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
2188222418{
2188322419 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);
......@@ -21900,6 +22436,7 @@ static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct
2190022436}
2190122437
2190222438static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {
22439 Error err;
2190322440 switch (tagTypeId) {
2190422441 case ZigTypeIdInvalid:
2190522442 zig_unreachable();
......@@ -21941,27 +22478,43 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
2194122478 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
2194222479 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
2194322480 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
21944 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen,
21945 get_const_field_meta_type(ira, payload, "child", 4),
22481 ZigType *elem_type = get_const_field_meta_type(ira, payload, "child", 4);
22482 ConstExprValue *sentinel;
22483 if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 6,
22484 elem_type, &sentinel)))
22485 {
22486 return nullptr;
22487 }
22488
22489 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
22490 elem_type,
2194622491 get_const_field_bool(ira, payload, "is_const", 1),
2194722492 get_const_field_bool(ira, payload, "is_volatile", 2),
2194822493 ptr_len,
2194922494 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),
2195022495 0, // bit_offset_in_host
2195122496 0, // host_int_bytes
21952 get_const_field_bool(ira, payload, "is_allowzero", 5)
21953 );
22497 get_const_field_bool(ira, payload, "is_allowzero", 5),
22498 VECTOR_INDEX_NONE, nullptr, sentinel);
2195422499 if (size_enum_index != 2)
2195522500 return ptr_type;
2195622501 return get_slice_type(ira->codegen, ptr_type);
2195722502 }
21958 case ZigTypeIdArray:
22503 case ZigTypeIdArray: {
2195922504 assert(payload->special == ConstValSpecialStatic);
2196022505 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));
22506 ZigType *elem_type = get_const_field_meta_type(ira, payload, "child", 1);
22507 ConstExprValue *sentinel;
22508 if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 2,
22509 elem_type, &sentinel)))
22510 {
22511 return nullptr;
22512 }
2196122513 return get_array_type(ira->codegen,
21962 get_const_field_meta_type(ira, payload, "child", 1),
21963 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0))
21964 );
22514 elem_type,
22515 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),
22516 sentinel);
22517 }
2196522518 case ZigTypeIdComptimeFloat:
2196622519 return ira->codegen->builtin_types.entry_num_lit_float;
2196722520 case ZigTypeIdComptimeInt:
......@@ -22343,7 +22896,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
2234322896 }
2234422897
2234522898 ZigType *result_type = get_array_type(ira->codegen,
22346 ira->codegen->builtin_types.entry_u8, buf_len(file_contents));
22899 ira->codegen->builtin_types.entry_u8, buf_len(file_contents), nullptr);
2234722900 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
2234822901 init_const_str_lit(ira->codegen, &result->value, file_contents);
2234922902 return result;
......@@ -25566,6 +26119,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
2556626119 result->value.data.x_lazy = &lazy_ptr_type->base;
2556726120 lazy_ptr_type->base.id = LazyValueIdPtrType;
2556826121
26122 if (instruction->sentinel != nullptr) {
26123 lazy_ptr_type->sentinel = instruction->sentinel->child;
26124 if (ir_resolve_const(ira, lazy_ptr_type->sentinel, LazyOk) == nullptr)
26125 return ira->codegen->invalid_instruction;
26126 }
26127
2556926128 lazy_ptr_type->elem_type = instruction->child_type->child;
2557026129 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
2557126130 return ira->codegen->invalid_instruction;
......@@ -26487,7 +27046,7 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
2648727046 ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child);
2648827047 if (type_is_invalid(dest_type))
2648927048 return ira->codegen->invalid_instruction;
26490 return ir_implicit_cast_with_result(ira, &instruction->base, operand, dest_type, nullptr);
27049 return ir_implicit_cast2(ira, &instruction->base, operand, dest_type);
2649127050}
2649227051
2649327052static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {
......@@ -27512,6 +28071,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2751228071 if (type_is_invalid(elem_type))
2751328072 return ErrorSemanticAnalyzeFail;
2751428073
28074 ConstExprValue *sentinel_val;
28075 if (lazy_slice_type->sentinel != nullptr) {
28076 if (type_is_invalid(lazy_slice_type->sentinel->value.type))
28077 return ErrorSemanticAnalyzeFail;
28078 IrInstruction *sentinel = ir_implicit_cast(ira, lazy_slice_type->sentinel, elem_type);
28079 if (type_is_invalid(sentinel->value.type))
28080 return ErrorSemanticAnalyzeFail;
28081 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
28082 if (sentinel_val == nullptr)
28083 return ErrorSemanticAnalyzeFail;
28084 } else {
28085 sentinel_val = nullptr;
28086 }
28087
2751528088 uint32_t align_bytes = 0;
2751628089 if (lazy_slice_type->align_inst != nullptr) {
2751728090 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))
......@@ -27557,9 +28130,12 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2755728130 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
2755828131 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
2755928132 return err;
27560 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,
27561 lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes,
27562 0, 0, lazy_slice_type->is_allowzero);
28133 ZigType *slice_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
28134 lazy_slice_type->is_const, lazy_slice_type->is_volatile,
28135 PtrLenUnknown,
28136 align_bytes,
28137 0, 0, lazy_slice_type->is_allowzero,
28138 VECTOR_INDEX_NONE, nullptr, sentinel_val);
2756328139 val->special = ConstValSpecialStatic;
2756428140 assert(val->type->id == ZigTypeIdMetaType);
2756528141 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);
......@@ -27573,6 +28149,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2757328149 if (type_is_invalid(elem_type))
2757428150 return ErrorSemanticAnalyzeFail;
2757528151
28152 ConstExprValue *sentinel_val;
28153 if (lazy_ptr_type->sentinel != nullptr) {
28154 if (type_is_invalid(lazy_ptr_type->sentinel->value.type))
28155 return ErrorSemanticAnalyzeFail;
28156 IrInstruction *sentinel = ir_implicit_cast(ira, lazy_ptr_type->sentinel, elem_type);
28157 if (type_is_invalid(sentinel->value.type))
28158 return ErrorSemanticAnalyzeFail;
28159 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
28160 if (sentinel_val == nullptr)
28161 return ErrorSemanticAnalyzeFail;
28162 } else {
28163 sentinel_val = nullptr;
28164 }
28165
2757628166 uint32_t align_bytes = 0;
2757728167 if (lazy_ptr_type->align_inst != nullptr) {
2757828168 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))
......@@ -27615,10 +28205,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
2761528205 }
2761628206 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
2761728207 assert(val->type->id == ZigTypeIdMetaType);
27618 val->data.x_type = get_pointer_to_type_extra(ira->codegen, elem_type,
28208 val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
2761928209 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,
2762028210 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,
27621 allow_zero);
28211 allow_zero, VECTOR_INDEX_NONE, nullptr, sentinel_val);
2762228212 val->special = ConstValSpecialStatic;
2762328213 return ErrorNone;
2762428214 }
src/parser.cpp+118-65
......@@ -848,7 +848,12 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
848848
849849 AstNode *type_expr = nullptr;
850850 if (eat_token_if(pc, TokenIdColon) != nullptr) {
851 type_expr = ast_expect(pc, ast_parse_type_expr);
851 Token *var_tok = eat_token_if(pc, TokenIdKeywordVar);
852 if (var_tok != nullptr) {
853 type_expr = ast_create_node(pc, NodeTypeVarFieldType, var_tok);
854 } else {
855 type_expr = ast_expect(pc, ast_parse_type_expr);
856 }
852857 }
853858 AstNode *align_expr = ast_parse_byte_align(pc);
854859 AstNode *expr = nullptr;
......@@ -1718,7 +1723,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
17181723 if (string_lit != nullptr) {
17191724 AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);
17201725 res->data.string_literal.buf = token_buf(string_lit);
1721 res->data.string_literal.c = string_lit->data.str_lit.is_c_str;
17221726 return res;
17231727 }
17241728
......@@ -1834,8 +1838,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {
18341838 return loop;
18351839 }
18361840
1837 if (label != nullptr)
1838 ast_invalid_token_error(pc, peek_token(pc));
1841 if (label != nullptr) {
1842 put_back_token(pc);
1843 put_back_token(pc);
1844 }
18391845 return nullptr;
18401846}
18411847
......@@ -1932,15 +1938,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {
19321938
19331939// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
19341940static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1935 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
1936 if (sym_name == nullptr) {
1937 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
1938 return nullptr;
1939 } else {
1940 sym_name = expect_token(pc, TokenIdSymbol);
1941 expect_token(pc, TokenIdRBracket);
1942 }
1943 }
1941 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1942 return nullptr;
1943
1944 Token *sym_name = expect_token(pc, TokenIdSymbol);
1945 expect_token(pc, TokenIdRBracket);
19441946
19451947 Token *str = expect_token(pc, TokenIdStringLiteral);
19461948 expect_token(pc, TokenIdLParen);
......@@ -1955,7 +1957,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
19551957 expect_token(pc, TokenIdRParen);
19561958
19571959 AsmOutput *res = allocate<AsmOutput>(1);
1958 res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
1960 res->asm_symbolic_name = token_buf(sym_name);
19591961 res->constraint = token_buf(str);
19601962 res->variable_name = token_buf(var_name);
19611963 res->return_type = return_type;
......@@ -1978,15 +1980,11 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {
19781980
19791981// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
19801982static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1981 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
1982 if (sym_name == nullptr) {
1983 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {
1984 return nullptr;
1985 } else {
1986 sym_name = expect_token(pc, TokenIdSymbol);
1987 expect_token(pc, TokenIdRBracket);
1988 }
1989 }
1983 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1984 return nullptr;
1985
1986 Token *sym_name = expect_token(pc, TokenIdSymbol);
1987 expect_token(pc, TokenIdRBracket);
19901988
19911989 Token *constraint = expect_token(pc, TokenIdStringLiteral);
19921990 expect_token(pc, TokenIdLParen);
......@@ -1994,7 +1992,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
19941992 expect_token(pc, TokenIdRParen);
19951993
19961994 AsmInput *res = allocate<AsmInput>(1);
1997 res->asm_symbolic_name = (sym_name->id == TokenIdBracketUnderscoreBracket) ? buf_create_from_str("_") : token_buf(sym_name);
1995 res->asm_symbolic_name = token_buf(sym_name);
19981996 res->constraint = token_buf(constraint);
19991997 res->expr = expr;
20001998 return res;
......@@ -2614,37 +2612,28 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
26142612 put_back_token(pc);
26152613 }
26162614
2617 AstNode *array = ast_parse_array_type_start(pc);
2618 if (array != nullptr) {
2619 assert(array->type == NodeTypeArrayType);
2620 while (true) {
2621 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2622 if (allowzero_token != nullptr) {
2623 array->data.array_type.allow_zero_token = allowzero_token;
2624 continue;
2625 }
2626
2627 AstNode *align_expr = ast_parse_byte_align(pc);
2628 if (align_expr != nullptr) {
2629 array->data.array_type.align_expr = align_expr;
2630 continue;
2631 }
2632
2633 if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
2634 array->data.array_type.is_const = true;
2635 continue;
2636 }
2637
2638 if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
2639 array->data.array_type.is_volatile = true;
2640 continue;
2615 Token *arr_init_lbracket = eat_token_if(pc, TokenIdLBracket);
2616 if (arr_init_lbracket != nullptr) {
2617 Token *underscore = eat_token_if(pc, TokenIdSymbol);
2618 if (underscore == nullptr) {
2619 put_back_token(pc);
2620 } else if (!buf_eql_str(token_buf(underscore), "_")) {
2621 put_back_token(pc);
2622 put_back_token(pc);
2623 } else {
2624 AstNode *sentinel = nullptr;
2625 Token *colon = eat_token_if(pc, TokenIdColon);
2626 if (colon != nullptr) {
2627 sentinel = ast_expect(pc, ast_parse_expr);
26412628 }
2642 break;
2629 expect_token(pc, TokenIdRBracket);
2630 AstNode *node = ast_create_node(pc, NodeTypeInferredArrayType, arr_init_lbracket);
2631 node->data.inferred_array_type.sentinel = sentinel;
2632 return node;
26432633 }
2644
2645 return array;
26462634 }
26472635
2636
26482637 AstNode *ptr = ast_parse_ptr_type_start(pc);
26492638 if (ptr != nullptr) {
26502639 assert(ptr->type == NodeTypePointerType);
......@@ -2690,9 +2679,35 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
26902679 return ptr;
26912680 }
26922681
2693 Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);
2694 if (arr_init != nullptr) {
2695 return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);
2682 AstNode *array = ast_parse_array_type_start(pc);
2683 if (array != nullptr) {
2684 assert(array->type == NodeTypeArrayType);
2685 while (true) {
2686 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);
2687 if (allowzero_token != nullptr) {
2688 array->data.array_type.allow_zero_token = allowzero_token;
2689 continue;
2690 }
2691
2692 AstNode *align_expr = ast_parse_byte_align(pc);
2693 if (align_expr != nullptr) {
2694 array->data.array_type.align_expr = align_expr;
2695 continue;
2696 }
2697
2698 if (eat_token_if(pc, TokenIdKeywordConst) != nullptr) {
2699 array->data.array_type.is_const = true;
2700 continue;
2701 }
2702
2703 if (eat_token_if(pc, TokenIdKeywordVolatile) != nullptr) {
2704 array->data.array_type.is_volatile = true;
2705 continue;
2706 }
2707 break;
2708 }
2709
2710 return array;
26962711 }
26972712
26982713
......@@ -2766,9 +2781,15 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27662781 return nullptr;
27672782
27682783 AstNode *size = ast_parse_expr(pc);
2784 AstNode *sentinel = nullptr;
2785 Token *colon = eat_token_if(pc, TokenIdColon);
2786 if (colon != nullptr) {
2787 sentinel = ast_expect(pc, ast_parse_expr);
2788 }
27692789 expect_token(pc, TokenIdRBracket);
27702790 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);
27712791 res->data.array_type.size = size;
2792 res->data.array_type.sentinel = sentinel;
27722793 return res;
27732794}
27742795
......@@ -2778,35 +2799,63 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
27782799// / PTRUNKNOWN
27792800// / PTRC
27802801static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2802 AstNode *sentinel = nullptr;
2803
27812804 Token *asterisk = eat_token_if(pc, TokenIdStar);
27822805 if (asterisk != nullptr) {
2806 Token *colon = eat_token_if(pc, TokenIdColon);
2807 if (colon != nullptr) {
2808 sentinel = ast_expect(pc, ast_parse_expr);
2809 }
27832810 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);
27842811 res->data.pointer_type.star_token = asterisk;
2812 res->data.pointer_type.sentinel = sentinel;
27852813 return res;
27862814 }
27872815
27882816 Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);
27892817 if (asterisk2 != nullptr) {
2818 Token *colon = eat_token_if(pc, TokenIdColon);
2819 if (colon != nullptr) {
2820 sentinel = ast_expect(pc, ast_parse_expr);
2821 }
27902822 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);
27912823 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);
27922824 res->data.pointer_type.star_token = asterisk2;
27932825 res2->data.pointer_type.star_token = asterisk2;
2826 res2->data.pointer_type.sentinel = sentinel;
27942827 res->data.pointer_type.op_expr = res2;
27952828 return res;
27962829 }
27972830
2798 Token *multptr = eat_token_if(pc, TokenIdBracketStarBracket);
2799 if (multptr != nullptr) {
2800 AstNode *res = ast_create_node(pc, NodeTypePointerType, multptr);
2801 res->data.pointer_type.star_token = multptr;
2802 return res;
2803 }
2831 Token *lbracket = eat_token_if(pc, TokenIdLBracket);
2832 if (lbracket != nullptr) {
2833 Token *star = eat_token_if(pc, TokenIdStar);
2834 if (star == nullptr) {
2835 put_back_token(pc);
2836 } else {
2837 Token *c_tok = eat_token_if(pc, TokenIdSymbol);
2838 if (c_tok != nullptr) {
2839 if (!buf_eql_str(token_buf(c_tok), "c")) {
2840 put_back_token(pc); // c symbol
2841 } else {
2842 expect_token(pc, TokenIdRBracket);
2843 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2844 res->data.pointer_type.star_token = c_tok;
2845 return res;
2846 }
2847 }
28042848
2805 Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
2806 if (cptr != nullptr) {
2807 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
2808 res->data.pointer_type.star_token = cptr;
2809 return res;
2849 Token *colon = eat_token_if(pc, TokenIdColon);
2850 if (colon != nullptr) {
2851 sentinel = ast_expect(pc, ast_parse_expr);
2852 }
2853 expect_token(pc, TokenIdRBracket);
2854 AstNode *res = ast_create_node(pc, NodeTypePointerType, lbracket);
2855 res->data.pointer_type.star_token = lbracket;
2856 res->data.pointer_type.sentinel = sentinel;
2857 return res;
2858 }
28102859 }
28112860
28122861 return nullptr;
......@@ -3084,10 +3133,12 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30843133 break;
30853134 case NodeTypeArrayType:
30863135 visit_field(&node->data.array_type.size, visit, context);
3136 visit_field(&node->data.array_type.sentinel, visit, context);
30873137 visit_field(&node->data.array_type.child_type, visit, context);
30883138 visit_field(&node->data.array_type.align_expr, visit, context);
30893139 break;
30903140 case NodeTypeInferredArrayType:
3141 visit_field(&node->data.array_type.sentinel, visit, context);
30913142 visit_field(&node->data.array_type.child_type, visit, context);
30923143 break;
30933144 case NodeTypeAnyFrameType:
......@@ -3097,6 +3148,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
30973148 // none
30983149 break;
30993150 case NodeTypePointerType:
3151 visit_field(&node->data.pointer_type.sentinel, visit, context);
31003152 visit_field(&node->data.pointer_type.align_expr, visit, context);
31013153 visit_field(&node->data.pointer_type.op_expr, visit, context);
31023154 break;
......@@ -3116,6 +3168,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
31163168 visit_field(&node->data.suspend.block, visit, context);
31173169 break;
31183170 case NodeTypeEnumLiteral:
3171 case NodeTypeVarFieldType:
31193172 break;
31203173 }
31213174}
src/tokenizer.cpp+4-118
......@@ -33,10 +33,10 @@
3333 '0': \
3434 case DIGIT_NON_ZERO
3535
36#define ALPHA_EXCEPT_C \
36#define ALPHA \
3737 'a': \
3838 case 'b': \
39 /*case 'c':*/ \
39 case 'c': \
4040 case 'd': \
4141 case 'e': \
4242 case 'f': \
......@@ -87,10 +87,6 @@
8787 case 'Y': \
8888 case 'Z'
8989
90#define ALPHA \
91 ALPHA_EXCEPT_C: \
92 case 'c'
93
9490#define SYMBOL_CHAR \
9591 ALPHA: \
9692 case DIGIT: \
......@@ -180,7 +176,6 @@ static bool is_symbol_char(uint8_t c) {
180176enum TokenizeState {
181177 TokenizeStateStart,
182178 TokenizeStateSymbol,
183 TokenizeStateSymbolFirstC,
184179 TokenizeStateZero, // "0", which might lead to "0x"
185180 TokenizeStateNumber, // "123", "0x123"
186181 TokenizeStateNumberDot,
......@@ -227,10 +222,6 @@ enum TokenizeState {
227222 TokenizeStateSawAtSign,
228223 TokenizeStateCharCode,
229224 TokenizeStateError,
230 TokenizeStateLBracket,
231 TokenizeStateLBracketStar,
232 TokenizeStateLBracketStarC,
233 TokenizeStateLBracketUnderscore,
234225};
235226
236227
......@@ -279,7 +270,6 @@ static void set_token_id(Tokenize *t, Token *token, TokenId id) {
279270 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {
280271 memset(&token->data.str_lit.str, 0, sizeof(Buf));
281272 buf_resize(&token->data.str_lit.str, 0);
282 token->data.str_lit.is_c_str = false;
283273 }
284274}
285275
......@@ -429,12 +419,7 @@ void tokenize(Buf *buf, Tokenization *out) {
429419 switch (c) {
430420 case WHITESPACE:
431421 break;
432 case 'c':
433 t.state = TokenizeStateSymbolFirstC;
434 begin_token(&t, TokenIdSymbol);
435 buf_append_char(&t.cur_tok->data.str_lit.str, c);
436 break;
437 case ALPHA_EXCEPT_C:
422 case ALPHA:
438423 case '_':
439424 t.state = TokenizeStateSymbol;
440425 begin_token(&t, TokenIdSymbol);
......@@ -491,8 +476,8 @@ void tokenize(Buf *buf, Tokenization *out) {
491476 end_token(&t);
492477 break;
493478 case '[':
494 t.state = TokenizeStateLBracket;
495479 begin_token(&t, TokenIdLBracket);
480 end_token(&t);
496481 break;
497482 case ']':
498483 begin_token(&t, TokenIdRBracket);
......@@ -786,62 +771,6 @@ void tokenize(Buf *buf, Tokenization *out) {
786771 continue;
787772 }
788773 break;
789 case TokenizeStateLBracket:
790 switch (c) {
791 case '*':
792 t.state = TokenizeStateLBracketStar;
793 break;
794 case '_':
795 t.state = TokenizeStateLBracketUnderscore;
796 break;
797 default:
798 // reinterpret as just an lbracket
799 t.pos -= 1;
800 end_token(&t);
801 t.state = TokenizeStateStart;
802 continue;
803 }
804 break;
805 case TokenizeStateLBracketUnderscore:
806 switch (c) {
807 case ']':
808 set_token_id(&t, t.cur_tok, TokenIdBracketUnderscoreBracket);
809 end_token(&t);
810 t.state = TokenizeStateStart;
811 break;
812 default:
813 // reinterpret as just an lbracket
814 t.pos -= 2;
815 end_token(&t);
816 t.state = TokenizeStateStart;
817 continue;
818 }
819 break;
820 case TokenizeStateLBracketStar:
821 switch (c) {
822 case 'c':
823 t.state = TokenizeStateLBracketStarC;
824 set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
825 break;
826 case ']':
827 set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
828 end_token(&t);
829 t.state = TokenizeStateStart;
830 break;
831 default:
832 invalid_char_error(&t, c);
833 }
834 break;
835 case TokenizeStateLBracketStarC:
836 switch (c) {
837 case ']':
838 end_token(&t);
839 t.state = TokenizeStateStart;
840 break;
841 default:
842 invalid_char_error(&t, c);
843 }
844 break;
845774 case TokenizeStateSawPlusPercent:
846775 switch (c) {
847776 case '=':
......@@ -1007,19 +936,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1007936 switch (c) {
1008937 case WHITESPACE:
1009938 break;
1010 case 'c':
1011 if (!t.cur_tok->data.str_lit.is_c_str) {
1012 t.pos -= 1;
1013 end_token(&t);
1014 t.state = TokenizeStateStart;
1015 break;
1016 }
1017 t.state = TokenizeStateLineStringContinueC;
1018 break;
1019939 case '\\':
1020 if (t.cur_tok->data.str_lit.is_c_str) {
1021 invalid_char_error(&t, c);
1022 }
1023940 t.state = TokenizeStateLineStringContinue;
1024941 break;
1025942 default:
......@@ -1084,29 +1001,6 @@ void tokenize(Buf *buf, Tokenization *out) {
10841001 break;
10851002 }
10861003 break;
1087 case TokenizeStateSymbolFirstC:
1088 switch (c) {
1089 case '"':
1090 set_token_id(&t, t.cur_tok, TokenIdStringLiteral);
1091 t.cur_tok->data.str_lit.is_c_str = true;
1092 t.state = TokenizeStateString;
1093 break;
1094 case '\\':
1095 set_token_id(&t, t.cur_tok, TokenIdStringLiteral);
1096 t.cur_tok->data.str_lit.is_c_str = true;
1097 t.state = TokenizeStateSawBackslash;
1098 break;
1099 case SYMBOL_CHAR:
1100 t.state = TokenizeStateSymbol;
1101 buf_append_char(&t.cur_tok->data.str_lit.str, c);
1102 break;
1103 default:
1104 t.pos -= 1;
1105 end_token(&t);
1106 t.state = TokenizeStateStart;
1107 continue;
1108 }
1109 break;
11101004 case TokenizeStateSawAtSign:
11111005 switch (c) {
11121006 case '"':
......@@ -1544,7 +1438,6 @@ void tokenize(Buf *buf, Tokenization *out) {
15441438 tokenize_error(&t, "unterminated character literal");
15451439 break;
15461440 case TokenizeStateSymbol:
1547 case TokenizeStateSymbolFirstC:
15481441 case TokenizeStateZero:
15491442 case TokenizeStateNumber:
15501443 case TokenizeStateFloatFraction:
......@@ -1572,7 +1465,6 @@ void tokenize(Buf *buf, Tokenization *out) {
15721465 case TokenizeStateLineString:
15731466 case TokenizeStateLineStringEnd:
15741467 case TokenizeStateSawBarBar:
1575 case TokenizeStateLBracket:
15761468 case TokenizeStateDocComment:
15771469 case TokenizeStateContainerDocComment:
15781470 end_token(&t);
......@@ -1581,9 +1473,6 @@ void tokenize(Buf *buf, Tokenization *out) {
15811473 case TokenizeStateSawBackslash:
15821474 case TokenizeStateLineStringContinue:
15831475 case TokenizeStateLineStringContinueC:
1584 case TokenizeStateLBracketStar:
1585 case TokenizeStateLBracketStarC:
1586 case TokenizeStateLBracketUnderscore:
15871476 tokenize_error(&t, "unexpected EOF");
15881477 break;
15891478 case TokenizeStateLineComment:
......@@ -1623,8 +1512,6 @@ const char * token_name(TokenId id) {
16231512 case TokenIdBitShiftRight: return ">>";
16241513 case TokenIdBitShiftRightEq: return ">>=";
16251514 case TokenIdBitXorEq: return "^=";
1626 case TokenIdBracketStarBracket: return "[*]";
1627 case TokenIdBracketStarCBracket: return "[*c]";
16281515 case TokenIdCharLiteral: return "CharLiteral";
16291516 case TokenIdCmpEq: return "==";
16301517 case TokenIdCmpGreaterOrEq: return ">=";
......@@ -1728,7 +1615,6 @@ const char * token_name(TokenId id) {
17281615 case TokenIdTimesPercent: return "*%";
17291616 case TokenIdTimesPercentEq: return "*%=";
17301617 case TokenIdBarBarEq: return "||=";
1731 case TokenIdBracketUnderscoreBracket: return "[_]";
17321618 case TokenIdCount:
17331619 zig_unreachable();
17341620 }
src/tokenizer.hpp-4
......@@ -28,9 +28,6 @@ enum TokenId {
2828 TokenIdBitShiftRight,
2929 TokenIdBitShiftRightEq,
3030 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
33 TokenIdBracketUnderscoreBracket,
3431 TokenIdCharLiteral,
3532 TokenIdCmpEq,
3633 TokenIdCmpGreaterOrEq,
......@@ -149,7 +146,6 @@ struct TokenIntLit {
149146
150147struct TokenStrLit {
151148 Buf str;
152 bool is_c_str;
153149};
154150
155151struct TokenCharLit {
src/translate_c.cpp+7-15
......@@ -291,9 +291,9 @@ static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
291291 case PtrLenSingle:
292292 return TokenIdStar;
293293 case PtrLenUnknown:
294 return TokenIdBracketStarBracket;
294 return TokenIdLBracket;
295295 case PtrLenC:
296 return TokenIdBracketStarCBracket;
296 return TokenIdSymbol;
297297 }
298298 zig_unreachable();
299299}
......@@ -321,17 +321,9 @@ static AstNode *trans_create_node_bool(Context *c, bool value) {
321321 return bool_node;
322322}
323323
324static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
324static AstNode *trans_create_node_str_lit(Context *c, Buf *buf) {
325325 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
326326 node->data.string_literal.buf = buf;
327 node->data.string_literal.c = true;
328 return node;
329}
330
331static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
332 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
333 node->data.string_literal.buf = buf;
334 node->data.string_literal.c = false;
335327 return node;
336328}
337329
......@@ -630,7 +622,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
630622// zig_type_node
631623
632624 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
633 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
625 import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("std")));
634626 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
635627 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
636628 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
......@@ -3389,7 +3381,7 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc
33893381 case ZigClangStringLiteral_StringKind_UTF8: {
33903382 size_t str_len;
33913383 const char *str_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &str_len);
3392 AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_mem(str_ptr, str_len));
3384 AstNode *node = trans_create_node_str_lit(c, buf_create_from_mem(str_ptr, str_len));
33933385 return maybe_suppress_result(c, result_used, node);
33943386 }
33953387 case ZigClangStringLiteral_StringKind_UTF16:
......@@ -4888,7 +4880,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
48884880 return trans_create_node_unsigned(c, tok->data.char_lit);
48894881 case CTokIdStrLit:
48904882 *tok_i += 1;
4891 return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
4883 return trans_create_node_str_lit(c, buf_create_from_buf(&tok->data.str_lit));
48924884 case CTokIdMinus:
48934885 *tok_i += 1;
48944886 return parse_ctok_num_lit(c, ctok, tok_i, true);
......@@ -4935,7 +4927,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
49354927 // (dest)(x)
49364928
49374929 AstNode *import_builtin = trans_create_node_builtin_fn_call_str(c, "import");
4938 import_builtin->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("builtin")));
4930 import_builtin->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("builtin")));
49394931 AstNode *typeid_type = trans_create_node_field_access_str(c, import_builtin, "TypeId");
49404932 AstNode *typeid_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");
49414933 AstNode *typeid_integer = trans_create_node_field_access_str(c, typeid_type, "Int");
test/cli.zig+1-1
......@@ -87,7 +87,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult {
8787fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
8888 _ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });
8989 const test_result = try exec(dir_path, [_][]const u8{ zig_exe, "build", "test" });
90 testing.expect(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n"));
90 testing.expect(std.mem.endsWith(u8, test_result.stderr, "All 1 tests passed.\n"));
9191}
9292
9393fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {
test/compare_output.zig+36-36
......@@ -7,7 +7,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
77 cases.addC("hello world with libc",
88 \\const c = @cImport(@cInclude("stdio.h"));
99 \\export fn main(argc: c_int, argv: [*][*]u8) c_int {
10 \\ _ = c.puts(c"Hello, world!");
10 \\ _ = c.puts("Hello, world!");
1111 \\ return 0;
1212 \\}
1313 , "Hello, world!" ++ std.cstr.line_sep);
......@@ -144,75 +144,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
144144 \\ // we want actual \n, not \r\n
145145 \\ _ = c._setmode(1, c._O_BINARY);
146146 \\ }
147 \\ _ = c.printf(c"0: %llu\n",
147 \\ _ = c.printf("0: %llu\n",
148148 \\ @as(u64, 0));
149 \\ _ = c.printf(c"320402575052271: %llu\n",
149 \\ _ = c.printf("320402575052271: %llu\n",
150150 \\ @as(u64, 320402575052271));
151 \\ _ = c.printf(c"0x01236789abcdef: %llu\n",
151 \\ _ = c.printf("0x01236789abcdef: %llu\n",
152152 \\ @as(u64, 0x01236789abcdef));
153 \\ _ = c.printf(c"0xffffffffffffffff: %llu\n",
153 \\ _ = c.printf("0xffffffffffffffff: %llu\n",
154154 \\ @as(u64, 0xffffffffffffffff));
155 \\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n",
155 \\ _ = c.printf("0x000000ffffffffffffffff: %llu\n",
156156 \\ @as(u64, 0x000000ffffffffffffffff));
157 \\ _ = c.printf(c"0o1777777777777777777777: %llu\n",
157 \\ _ = c.printf("0o1777777777777777777777: %llu\n",
158158 \\ @as(u64, 0o1777777777777777777777));
159 \\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n",
159 \\ _ = c.printf("0o0000001777777777777777777777: %llu\n",
160160 \\ @as(u64, 0o0000001777777777777777777777));
161 \\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
161 \\ _ = c.printf("0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
162162 \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111));
163 \\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
163 \\ _ = c.printf("0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
164164 \\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111));
165165 \\
166 \\ _ = c.printf(c"\n");
166 \\ _ = c.printf("\n");
167167 \\
168 \\ _ = c.printf(c"0.0: %.013a\n",
168 \\ _ = c.printf("0.0: %.013a\n",
169169 \\ @as(f64, 0.0));
170 \\ _ = c.printf(c"0e0: %.013a\n",
170 \\ _ = c.printf("0e0: %.013a\n",
171171 \\ @as(f64, 0e0));
172 \\ _ = c.printf(c"0.0e0: %.013a\n",
172 \\ _ = c.printf("0.0e0: %.013a\n",
173173 \\ @as(f64, 0.0e0));
174 \\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
174 \\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
175175 \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));
176 \\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
176 \\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
177177 \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));
178 \\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
178 \\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
179179 \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000));
180 \\ _ = c.printf(c"1.0: %.013a\n",
180 \\ _ = c.printf("1.0: %.013a\n",
181181 \\ @as(f64, 1.0));
182 \\ _ = c.printf(c"10.0: %.013a\n",
182 \\ _ = c.printf("10.0: %.013a\n",
183183 \\ @as(f64, 10.0));
184 \\ _ = c.printf(c"10.5: %.013a\n",
184 \\ _ = c.printf("10.5: %.013a\n",
185185 \\ @as(f64, 10.5));
186 \\ _ = c.printf(c"10.5e5: %.013a\n",
186 \\ _ = c.printf("10.5e5: %.013a\n",
187187 \\ @as(f64, 10.5e5));
188 \\ _ = c.printf(c"10.5e+5: %.013a\n",
188 \\ _ = c.printf("10.5e+5: %.013a\n",
189189 \\ @as(f64, 10.5e+5));
190 \\ _ = c.printf(c"50.0e-2: %.013a\n",
190 \\ _ = c.printf("50.0e-2: %.013a\n",
191191 \\ @as(f64, 50.0e-2));
192 \\ _ = c.printf(c"50e-2: %.013a\n",
192 \\ _ = c.printf("50e-2: %.013a\n",
193193 \\ @as(f64, 50e-2));
194194 \\
195 \\ _ = c.printf(c"\n");
195 \\ _ = c.printf("\n");
196196 \\
197 \\ _ = c.printf(c"0x1.0: %.013a\n",
197 \\ _ = c.printf("0x1.0: %.013a\n",
198198 \\ @as(f64, 0x1.0));
199 \\ _ = c.printf(c"0x10.0: %.013a\n",
199 \\ _ = c.printf("0x10.0: %.013a\n",
200200 \\ @as(f64, 0x10.0));
201 \\ _ = c.printf(c"0x100.0: %.013a\n",
201 \\ _ = c.printf("0x100.0: %.013a\n",
202202 \\ @as(f64, 0x100.0));
203 \\ _ = c.printf(c"0x103.0: %.013a\n",
203 \\ _ = c.printf("0x103.0: %.013a\n",
204204 \\ @as(f64, 0x103.0));
205 \\ _ = c.printf(c"0x103.7: %.013a\n",
205 \\ _ = c.printf("0x103.7: %.013a\n",
206206 \\ @as(f64, 0x103.7));
207 \\ _ = c.printf(c"0x103.70: %.013a\n",
207 \\ _ = c.printf("0x103.70: %.013a\n",
208208 \\ @as(f64, 0x103.70));
209 \\ _ = c.printf(c"0x103.70p4: %.013a\n",
209 \\ _ = c.printf("0x103.70p4: %.013a\n",
210210 \\ @as(f64, 0x103.70p4));
211 \\ _ = c.printf(c"0x103.70p5: %.013a\n",
211 \\ _ = c.printf("0x103.70p5: %.013a\n",
212212 \\ @as(f64, 0x103.70p5));
213 \\ _ = c.printf(c"0x103.70p+5: %.013a\n",
213 \\ _ = c.printf("0x103.70p+5: %.013a\n",
214214 \\ @as(f64, 0x103.70p+5));
215 \\ _ = c.printf(c"0x103.70p-5: %.013a\n",
215 \\ _ = c.printf("0x103.70p-5: %.013a\n",
216216 \\ @as(f64, 0x103.70p-5));
217217 \\
218218 \\ return 0;
......@@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
323323 \\ const x: f64 = small;
324324 \\ const y = @floatToInt(i32, x);
325325 \\ const z = @intToFloat(f64, y);
326 \\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4));
326 \\ _ = c.printf("%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4));
327327 \\ return 0;
328328 \\}
329329 , "3.25\n3\n3.00\n-0.40\n");
test/compile_errors.zig+58-17
......@@ -2,6 +2,33 @@ const tests = @import("tests.zig");
22const builtin = @import("builtin");
33
44pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add(
6 "incompatible sentinels",
7 \\export fn entry1(ptr: [*:255]u8) [*:0]u8 {
8 \\ return ptr;
9 \\}
10 \\export fn entry2(ptr: [*]u8) [*:0]u8 {
11 \\ return ptr;
12 \\}
13 \\export fn entry3() void {
14 \\ var array: [2:0]u8 = [_:255]u8{1, 2};
15 \\}
16 \\export fn entry4() void {
17 \\ var array: [2:0]u8 = [_]u8{1, 2};
18 \\}
19 ,
20 "tmp.zig:2:12: error: expected type '[*:0]u8', found '[*:255]u8'",
21 "tmp.zig:2:12: note: destination pointer requires a terminating '0' sentinel, but source pointer has a terminating '255' sentinel",
22 "tmp.zig:5:12: error: expected type '[*:0]u8', found '[*]u8'",
23 "tmp.zig:5:12: note: destination pointer requires a terminating '0' sentinel",
24
25 "tmp.zig:8:35: error: expected type '[2:0]u8', found '[2:255]u8'",
26 "tmp.zig:8:35: note: destination array requires a terminating '0' sentinel, but source array has a terminating '255' sentinel",
27 "tmp.zig:11:31: error: expected type '[2:0]u8', found '[2]u8'",
28 "tmp.zig:11:31: note: destination array requires a terminating '0' sentinel",
29
30 );
31
532 cases.add(
633 "empty switch on an integer",
734 \\export fn entry() void {
......@@ -99,6 +126,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
99126 "tmp.zig:9:27: error: @atomicRmw on enum only works with .Xchg",
100127 );
101128
129 cases.add(
130 "disallow coercion from non-null-terminated pointer to null-terminated pointer",
131 \\extern fn puts(s: [*:0]const u8) c_int;
132 \\pub fn main() void {
133 \\ const no_zero_array = [_]u8{'h', 'e', 'l', 'l', 'o'};
134 \\ const no_zero_ptr: [*]const u8 = &no_zero_array;
135 \\ _ = puts(no_zero_ptr);
136 \\}
137 ,
138 "tmp.zig:5:14: error: expected type '[*:0]const u8', found '[*]const u8'",
139 );
140
102141 cases.add(
103142 "atomic orderings of atomicStore Acquire or AcqRel",
104143 \\export fn entry() void {
......@@ -183,7 +222,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
183222 cases.add(
184223 "using an unknown len ptr type instead of array",
185224 \\const resolutions = [*][*]const u8{
186 \\ c"[320 240 ]",
225 \\ "[320 240 ]",
187226 \\ null,
188227 \\};
189228 \\comptime {
......@@ -800,10 +839,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
800839 "peer cast then implicit cast const pointer to mutable C pointer",
801840 \\export fn func() void {
802841 \\ var strValue: [*c]u8 = undefined;
803 \\ strValue = strValue orelse c"";
842 \\ strValue = strValue orelse "";
804843 \\}
805844 ,
806 "tmp.zig:3:32: error: cast discards const qualifier",
845 "tmp.zig:3:32: error: expected type '[*c]u8', found '*const [0:0]u8'",
846 "tmp.zig:3:32: note: cast discards const qualifier",
807847 );
808848
809849 cases.add(
......@@ -1134,7 +1174,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
11341174 "libc headers note",
11351175 \\const c = @cImport(@cInclude("stdio.h"));
11361176 \\export fn entry() void {
1137 \\ _ = c.printf(c"hello, world!\n");
1177 \\ _ = c.printf("hello, world!\n");
11381178 \\}
11391179 ,
11401180 "tmp.zig:1:11: error: C import failed",
......@@ -1342,7 +1382,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
13421382 \\ ptr_opt_many_ptr = c_ptr;
13431383 \\}
13441384 \\export fn entry2() void {
1345 \\ var buf: [4]u8 = "aoeu";
1385 \\ var buf: [4]u8 = "aoeu".*;
13461386 \\ var slice: []u8 = &buf;
13471387 \\ var opt_many_ptr: [*]u8 = slice.ptr;
13481388 \\ var ptr_opt_many_ptr = &opt_many_ptr;
......@@ -1537,7 +1577,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
15371577 cases.add(
15381578 "reading past end of pointer casted array",
15391579 \\comptime {
1540 \\ const array = "aoeu";
1580 \\ const array: [4]u8 = "aoeu".*;
15411581 \\ const slice = array[1..];
15421582 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
15431583 \\ const deref = int_ptr.*;
......@@ -2460,12 +2500,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
24602500 );
24612501
24622502 cases.add(
2463 "var not allowed in structs",
2503 "var makes structs required to be comptime known",
24642504 \\export fn entry() void {
2465 \\ var s = (struct{v: var}){.v=@as(i32, 10)};
2505 \\ const S = struct{v: var};
2506 \\ var s = S{.v=@as(i32, 10)};
24662507 \\}
24672508 ,
2468 "tmp.zig:2:23: error: invalid token: 'var'",
2509 "tmp.zig:3:4: error: variable of type 'S' must be const or comptime",
24692510 );
24702511
24712512 cases.add(
......@@ -3371,11 +3412,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
33713412 cases.add(
33723413 "variable has wrong type",
33733414 \\export fn f() i32 {
3374 \\ const a = c"a";
3415 \\ const a = "a";
33753416 \\ return a;
33763417 \\}
33773418 ,
3378 "tmp.zig:3:12: error: expected type 'i32', found '[*]const u8'",
3419 "tmp.zig:3:12: error: expected type 'i32', found '*const [1:0]u8'",
33793420 );
33803421
33813422 cases.add(
......@@ -3846,12 +3887,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
38463887 cases.add(
38473888 "array concatenation with wrong type",
38483889 \\const src = "aoeu";
3849 \\const derp = @as(usize, 1234);
3890 \\const derp: usize = 1234;
38503891 \\const a = derp ++ "foo";
38513892 \\
38523893 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
38533894 ,
3854 "tmp.zig:3:11: error: expected array or C string literal, found 'usize'",
3895 "tmp.zig:3:11: error: expected array, found 'usize'",
38553896 );
38563897
38573898 cases.add(
......@@ -4805,7 +4846,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
48054846 cases.add(
48064847 "assign through constant pointer",
48074848 \\export fn f() void {
4808 \\ var cstr = c"Hat";
4849 \\ var cstr = "Hat";
48094850 \\ cstr[0] = 'W';
48104851 \\}
48114852 ,
......@@ -6226,11 +6267,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
62266267 cases.add(
62276268 "calling var args extern function, passing array instead of pointer",
62286269 \\export fn entry() void {
6229 \\ foo("hello",);
6270 \\ foo("hello".*,);
62306271 \\}
62316272 \\pub extern fn foo(format: *const u8, ...) void;
62326273 ,
6233 "tmp.zig:2:9: error: expected type '*const u8', found '[5]u8'",
6274 "tmp.zig:2:16: error: expected type '*const u8', found '[5:0]u8'",
62346275 );
62356276
62366277 cases.add(
......@@ -6796,7 +6837,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
67966837 \\}
67976838 ,
67986839 "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'",
6799 "tmp.zig:4:22: note: pointer type child 'i32' cannot cast into pointer type child '[1]i32'",
6840 "tmp.zig:4:22: note: cast discards const qualifier",
68006841 );
68016842
68026843 cases.add(
test/stage1/behavior/array.zig+33-6
......@@ -132,9 +132,16 @@ test "single-item pointer to array indexing and slicing" {
132132}
133133
134134fn testSingleItemPtrArrayIndexSlice() void {
135 var array = "aaaa";
136 doSomeMangling(&array);
137 expect(mem.eql(u8, "azya", array));
135 {
136 var array: [4]u8 = "aaaa".*;
137 doSomeMangling(&array);
138 expect(mem.eql(u8, "azya", &array));
139 }
140 {
141 var array = "aaaa".*;
142 doSomeMangling(&array);
143 expect(mem.eql(u8, "azya", &array));
144 }
138145}
139146
140147fn doSomeMangling(array: *[4]u8) void {
......@@ -294,9 +301,16 @@ test "read/write through global variable array of struct fields initialized via
294301}
295302
296303test "implicit cast zero sized array ptr to slice" {
297 var b = "";
298 const c: []const u8 = &b;
299 expect(c.len == 0);
304 {
305 var b = "".*;
306 const c: []const u8 = &b;
307 expect(c.len == 0);
308 }
309 {
310 var b: [0]u8 = "".*;
311 const c: []const u8 = &b;
312 expect(c.len == 0);
313 }
300314}
301315
302316test "anonymous list literal syntax" {
......@@ -333,3 +347,16 @@ test "anonymous literal in array" {
333347 S.doTheTest();
334348 comptime S.doTheTest();
335349}
350
351test "access the null element of a null terminated array" {
352 const S = struct {
353 fn doTheTest() void {
354 var array: [4:0]u8 = .{'a', 'o', 'e', 'u'};
355 comptime expect(array[4] == 0);
356 var len: usize = 4;
357 expect(array[len] == 0);
358 }
359 };
360 S.doTheTest();
361 comptime S.doTheTest();
362}
test/stage1/behavior/bugs/1076.zig+12-4
......@@ -8,8 +8,16 @@ test "comptime code should not modify constant data" {
88}
99
1010fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";
12 const x: [*]u8 = &array;
13 x[0] += 1;
14 expect(mem.eql(u8, array[0..], "boeu"));
11 {
12 var array = "aoeu".*;
13 const x: [*]u8 = &array;
14 x[0] += 1;
15 expect(mem.eql(u8, array[0..], "boeu"));
16 }
17 {
18 var array: [4]u8 = "aoeu".*;
19 const x: [*]u8 = &array;
20 x[0] += 1;
21 expect(mem.eql(u8, array[0..], "boeu"));
22 }
1523}
test/stage1/behavior/cast.zig+137-28
......@@ -179,18 +179,24 @@ fn gimmeErrOrSlice() anyerror![]u8 {
179179}
180180
181181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
182 {
183 var data = "hi";
184 const slice = data[0..];
185 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
186 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
187 }
188 comptime {
189 var data = "hi";
190 const slice = data[0..];
191 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
192 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
193 }
182 const S = struct {
183 fn doTheTest() anyerror!void {
184 {
185 var data = "hi".*;
186 const slice = data[0..];
187 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
188 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
189 }
190 {
191 var data: [2]u8 = "hi".*;
192 const slice = data[0..];
193 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
194 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
195 }
196 }
197 };
198 try S.doTheTest();
199 try comptime S.doTheTest();
194200}
195201fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
196202 if (a) {
......@@ -217,11 +223,20 @@ test "implicit cast from &const [N]T to []const T" {
217223}
218224
219225fn testCastConstArrayRefToConstSlice() void {
220 const blah = "aoeu";
221 const const_array_ref = &blah;
222 expect(@typeOf(const_array_ref) == *const [4]u8);
223 const slice: []const u8 = const_array_ref;
224 expect(mem.eql(u8, slice, "aoeu"));
226 {
227 const blah = "aoeu".*;
228 const const_array_ref = &blah;
229 expect(@typeOf(const_array_ref) == *const [4:0]u8);
230 const slice: []const u8 = const_array_ref;
231 expect(mem.eql(u8, slice, "aoeu"));
232 }
233 {
234 const blah: [4]u8 = "aoeu".*;
235 const const_array_ref = &blah;
236 expect(@typeOf(const_array_ref) == *const [4]u8);
237 const slice: []const u8 = const_array_ref;
238 expect(mem.eql(u8, slice, "aoeu"));
239 }
225240}
226241
227242test "peer type resolution: error and [N]T" {
......@@ -310,19 +325,30 @@ test "single-item pointer of array to slice and to unknown length pointer" {
310325}
311326
312327fn testCastPtrOfArrayToSliceAndPtr() void {
313 var array = "aoeu";
314 const x: [*]u8 = &array;
315 x[0] += 1;
316 expect(mem.eql(u8, array[0..], "boeu"));
317 const y: []u8 = &array;
318 y[0] += 1;
319 expect(mem.eql(u8, array[0..], "coeu"));
328 {
329 var array = "aoeu".*;
330 const x: [*]u8 = &array;
331 x[0] += 1;
332 expect(mem.eql(u8, array[0..], "boeu"));
333 const y: []u8 = &array;
334 y[0] += 1;
335 expect(mem.eql(u8, array[0..], "coeu"));
336 }
337 {
338 var array: [4]u8 = "aoeu".*;
339 const x: [*]u8 = &array;
340 x[0] += 1;
341 expect(mem.eql(u8, array[0..], "boeu"));
342 const y: []u8 = &array;
343 y[0] += 1;
344 expect(mem.eql(u8, array[0..], "coeu"));
345 }
320346}
321347
322348test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
323 const window_name = [1][*]const u8{c"window name"};
349 const window_name = [1][*]const u8{"window name"};
324350 const x: [*]const ?[*]const u8 = &window_name;
325 expect(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
351 expect(mem.eql(u8, std.mem.toSliceConst(u8, @ptrCast([*:0]const u8, x[0].?)), "window name"));
326352}
327353
328354test "@intCast comptime_int" {
......@@ -545,7 +571,7 @@ test "implicit cast *[0]T to E![]const u8" {
545571}
546572
547573test "peer cast *[0]T to E![]const T" {
548 var buffer: [5]u8 = "abcde";
574 var buffer: [5]u8 = "abcde".*;
549575 var buf: anyerror![]const u8 = buffer[0..];
550576 var b = false;
551577 var y = if (b) &[0]u8{} else buf;
......@@ -553,7 +579,7 @@ test "peer cast *[0]T to E![]const T" {
553579}
554580
555581test "peer cast *[0]T to []const T" {
556 var buffer: [5]u8 = "abcde";
582 var buffer: [5]u8 = "abcde".*;
557583 var buf: []const u8 = buffer[0..];
558584 var b = false;
559585 var y = if (b) &[0]u8{} else buf;
......@@ -565,3 +591,86 @@ test "cast from array reference to fn" {
565591 const f = @ptrCast(extern fn () void, &global_array);
566592 expect(@ptrToInt(f) == @ptrToInt(&global_array));
567593}
594
595test "*const [N]null u8 to ?[]const u8" {
596 const S = struct {
597 fn doTheTest() void {
598 var a = "Hello";
599 var b: ?[]const u8 = a;
600 expect(mem.eql(u8, b.?, "Hello"));
601 }
602 };
603 S.doTheTest();
604 comptime S.doTheTest();
605}
606
607test "peer resolution of string literals" {
608 const S = struct {
609 const E = extern enum { a, b, c, d};
610
611 fn doTheTest(e: E) void {
612 const cmd = switch (e) {
613 .a => "one",
614 .b => "two",
615 .c => "three",
616 .d => "four",
617 };
618 expect(mem.eql(u8, cmd, "two"));
619 }
620 };
621 S.doTheTest(.b);
622 comptime S.doTheTest(.b);
623}
624
625test "type coercion related to sentinel-termination" {
626 const S = struct {
627 fn doTheTest() void {
628 // [:x]T to []T
629 {
630 var array = [4:0]i32{1,2,3,4};
631 var slice: [:0]i32 = &array;
632 var dest: []i32 = slice;
633 expect(mem.eql(i32, dest, &[_]i32{1,2,3,4}));
634 }
635
636 // [*:x]T to [*]T
637 {
638 var array = [4:99]i32{1,2,3,4};
639 var dest: [*]i32 = &array;
640 expect(dest[0] == 1);
641 expect(dest[1] == 2);
642 expect(dest[2] == 3);
643 expect(dest[3] == 4);
644 expect(dest[4] == 99);
645 }
646
647 // [N:x]T to [N]T
648 {
649 var array = [4:0]i32{1,2,3,4};
650 var dest: [4]i32 = array;
651 expect(mem.eql(i32, dest, &[_]i32{1,2,3,4}));
652 }
653
654 // *[N:x]T to *[N]T
655 {
656 var array = [4:0]i32{1,2,3,4};
657 var dest: *[4]i32 = &array;
658 expect(mem.eql(i32, dest, &[_]i32{1,2,3,4}));
659 }
660
661 // [:x]T to [*:x]T
662 {
663 var array = [4:0]i32{1,2,3,4};
664 var slice: [:0]i32 = &array;
665 var dest: [*:0]i32 = slice;
666 expect(dest[0] == 1);
667 expect(dest[1] == 2);
668 expect(dest[2] == 3);
669 expect(dest[3] == 4);
670 expect(dest[4] == 0);
671 }
672 }
673 };
674 S.doTheTest();
675 comptime S.doTheTest();
676}
test/stage1/behavior/const_slice_child.zig+4-5
......@@ -6,12 +6,11 @@ var argv: [*]const [*]const u8 = undefined;
66
77test "const slice child" {
88 const strs = [_][*]const u8{
9 c"one",
10 c"two",
11 c"three",
9 "one",
10 "two",
11 "three",
1212 };
13 // TODO this should implicitly cast
14 argv = @ptrCast([*]const [*]const u8, &strs);
13 argv = &strs;
1514 bar(strs.len);
1615}
1716
test/stage1/behavior/eval.zig+1-1
......@@ -736,7 +736,7 @@ test "comptime pointer cast array and then slice" {
736736
737737test "slice bounds in comptime concatenation" {
738738 const bs = comptime blk: {
739 const b = c"........1........";
739 const b = "........1........";
740740 break :blk b[8..9];
741741 };
742742 const str = "" ++ bs;
test/stage1/behavior/if.zig+4
......@@ -81,6 +81,10 @@ test "if prongs cast to expected type instead of peer type resolution" {
8181 var x: i32 = 0;
8282 x = if (f) 1 else 2;
8383 expect(x == 2);
84
85 var b = true;
86 const y: i32 = if (b) 1 else 2;
87 expect(y == 1);
8488 }
8589 };
8690 S.doTheTest(false);
test/stage1/behavior/misc.zig+10-7
......@@ -204,11 +204,11 @@ test "multiline string" {
204204
205205test "multiline C string" {
206206 const s1 =
207 c\\one
208 c\\two)
209 c\\three
207 \\one
208 \\two)
209 \\three
210210 ;
211 const s2 = c"one\ntwo)\nthree";
211 const s2 = "one\ntwo)\nthree";
212212 expect(std.cstr.cmp(s1, s2) == 0);
213213}
214214
......@@ -358,9 +358,12 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358358 return a == b;
359359}
360360
361test "C string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";
363 const b = c"OK IT WORKED";
361test "string concatenation" {
362 const a = "OK" ++ " IT " ++ "WORKED";
363 const b = "OK IT WORKED";
364
365 comptime expect(@typeOf(a) == *const [12:0]u8);
366 comptime expect(@typeOf(b) == *const [12:0]u8);
364367
365368 const len = mem.len(u8, b);
366369 const len_with_null = len + 1;
test/stage1/behavior/pointers.zig+63-1
......@@ -15,7 +15,7 @@ fn testDerefPtr() void {
1515}
1616
1717test "pointer arithmetic" {
18 var ptr = c"abcd";
18 var ptr: [*]const u8 = "abcd";
1919
2020 expect(ptr[0] == 'a');
2121 ptr += 1;
......@@ -200,3 +200,65 @@ test "assign null directly to C pointer and test null equality" {
200200 }
201201 comptime expect((y1 orelse &othery) == y1);
202202}
203
204test "null terminated pointer" {
205 const S = struct {
206 fn doTheTest() void {
207 var array_with_zero = [_:0]u8{'h', 'e', 'l', 'l', 'o'};
208 var zero_ptr: [*:0]const u8 = @ptrCast([*:0]const u8, &array_with_zero);
209 var no_zero_ptr: [*]const u8 = zero_ptr;
210 var zero_ptr_again = @ptrCast([*:0]const u8, no_zero_ptr);
211 expect(std.mem.eql(u8, std.mem.toSliceConst(u8, zero_ptr_again), "hello"));
212 }
213 };
214 S.doTheTest();
215 comptime S.doTheTest();
216}
217
218test "allow any sentinel" {
219 const S = struct {
220 fn doTheTest() void {
221 var array = [_:std.math.minInt(i32)]i32{1, 2, 3, 4};
222 var ptr: [*:std.math.minInt(i32)]i32 = &array;
223 expect(ptr[4] == std.math.minInt(i32));
224 }
225 };
226 S.doTheTest();
227 comptime S.doTheTest();
228}
229
230test "pointer sentinel with enums" {
231 const S = struct {
232 const Number = enum{one, two, sentinel};
233
234 fn doTheTest() void {
235 var ptr: [*:.sentinel]Number = &[_:.sentinel]Number{.one, .two, .two, .one};
236 expect(ptr[4] == .sentinel); // TODO this should be comptime expect, see #3731
237 }
238 };
239 S.doTheTest();
240 comptime S.doTheTest();
241}
242
243test "pointer sentinel with optional element" {
244 const S = struct {
245 fn doTheTest() void {
246 var ptr: [*:null]?i32 = &[_:null]?i32{1, 2, 3, 4};
247 expect(ptr[4] == null); // TODO this should be comptime expect, see #3731
248 }
249 };
250 S.doTheTest();
251 comptime S.doTheTest();
252}
253
254test "pointer sentinel with +inf" {
255 const S = struct {
256 fn doTheTest() void {
257 const inf = std.math.inf_f32;
258 var ptr: [*:inf]f32 = &[_:inf]f32{1.1, 2.2, 3.3, 4.4};
259 expect(ptr[4] == inf); // TODO this should be comptime expect, see #3731
260 }
261 };
262 S.doTheTest();
263 comptime S.doTheTest();
264}
test/stage1/behavior/ptrcast.zig+1-1
......@@ -60,7 +60,7 @@ test "comptime ptrcast keeps larger alignment" {
6060}
6161
6262test "implicit optional pointer to optional c_void pointer" {
63 var buf: [4]u8 = "aoeu";
63 var buf: [4]u8 = "aoeu".*;
6464 var x: ?[*]u8 = &buf;
6565 var y: ?*c_void = x;
6666 var z = @ptrCast(*[4]u8, y);
test/stage1/behavior/slice.zig+14-1
......@@ -36,7 +36,7 @@ fn assertLenIsZero(msg: []const u8) void {
3636}
3737
3838test "C pointer" {
39 var buf: [*c]const u8 = c"kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
39 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
4040 var len: u32 = 10;
4141 var slice = buf[0..len];
4242 expectEqualSlices(u8, "kjdhfkjdhf", slice);
......@@ -65,3 +65,16 @@ test "slice type with custom alignment" {
6565 slice[1].anything = 42;
6666 expect(array[1].anything == 42);
6767}
68
69test "access len index of sentinel-terminated slice" {
70 const S = struct {
71 fn doTheTest() void {
72 var slice: [:0]const u8 = "hello";
73
74 expect(slice.len == 5);
75 expect(slice[5] == 0);
76 }
77 };
78 S.doTheTest();
79 comptime S.doTheTest();
80}
test/stage1/behavior/struct.zig+14-1
......@@ -493,7 +493,7 @@ test "non-byte-aligned array inside packed struct" {
493493 fn doTheTest() void {
494494 var foo = Foo{
495495 .a = true,
496 .b = "abcdefghijklmnopqurstu",
496 .b = "abcdefghijklmnopqurstu".*,
497497 };
498498 bar(foo.b);
499499 }
......@@ -777,3 +777,16 @@ test "anonymous struct literal assigned to variable" {
777777 vec.@"1" += 1;
778778 expect(vec.@"1" == 56);
779779}
780
781test "struct with var field" {
782 const Point = struct {
783 x: var,
784 y: var,
785 };
786 const pt = Point {
787 .x = 1,
788 .y = 2,
789 };
790 expect(pt.x == 1);
791 expect(pt.y == 2);
792}
test/stage1/behavior/type.zig+83-64
......@@ -11,103 +11,122 @@ fn testTypes(comptime types: []const type) void {
1111}
1212
1313test "Type.MetaType" {
14 testing.expect(type == @Type(TypeInfo { .Type = undefined }));
15 testTypes([_]type {type});
14 testing.expect(type == @Type(TypeInfo{ .Type = undefined }));
15 testTypes([_]type{type});
1616}
1717
1818test "Type.Void" {
19 testing.expect(void == @Type(TypeInfo { .Void = undefined }));
20 testTypes([_]type {void});
19 testing.expect(void == @Type(TypeInfo{ .Void = undefined }));
20 testTypes([_]type{void});
2121}
2222
2323test "Type.Bool" {
24 testing.expect(bool == @Type(TypeInfo { .Bool = undefined }));
25 testTypes([_]type {bool});
24 testing.expect(bool == @Type(TypeInfo{ .Bool = undefined }));
25 testTypes([_]type{bool});
2626}
2727
2828test "Type.NoReturn" {
29 testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined }));
30 testTypes([_]type {noreturn});
29 testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined }));
30 testTypes([_]type{noreturn});
3131}
3232
3333test "Type.Int" {
34 testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } }));
35 testing.expect(i1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 1 } }));
36 testing.expect(u8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 8 } }));
37 testing.expect(i8 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 8 } }));
38 testing.expect(u64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 64 } }));
39 testing.expect(i64 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = true, .bits = 64 } }));
40 testTypes([_]type {u8,u32,i64});
34 testing.expect(u1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 1 } }));
35 testing.expect(i1 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 1 } }));
36 testing.expect(u8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 8 } }));
37 testing.expect(i8 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 8 } }));
38 testing.expect(u64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = false, .bits = 64 } }));
39 testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 64 } }));
40 testTypes([_]type{ u8, u32, i64 });
4141}
4242
4343test "Type.Float" {
44 testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } }));
45 testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } }));
46 testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } }));
47 testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } }));
48 testTypes([_]type {f16, f32, f64, f128});
44 testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
45 testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
46 testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
47 testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
48 testTypes([_]type{ f16, f32, f64, f128 });
4949}
5050
5151test "Type.Pointer" {
52 testTypes([_]type {
52 testTypes([_]type{
5353 // One Value Pointer Types
54 *u8, *const u8,
55 *volatile u8, *const volatile u8,
56 *align(4) u8, *const align(4) u8,
57 *volatile align(4) u8, *const volatile align(4) u8,
58 *align(8) u8, *const align(8) u8,
59 *volatile align(8) u8, *const volatile align(8) u8,
60 *allowzero u8, *const allowzero u8,
61 *volatile allowzero u8, *const volatile allowzero u8,
62 *align(4) allowzero u8, *const align(4) allowzero u8,
63 *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8,
54 *u8, *const u8,
55 *volatile u8, *const volatile u8,
56 *align(4) u8, *align(4) const u8,
57 *align(4) volatile u8, *align(4) const volatile u8,
58 *align(8) u8, *align(8) const u8,
59 *align(8) volatile u8, *align(8) const volatile u8,
60 *allowzero u8, *allowzero const u8,
61 *allowzero volatile u8, *allowzero const volatile u8,
62 *allowzero align(4) u8, *allowzero align(4) const u8,
63 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
6464 // Many Values Pointer Types
65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]const align(4) u8,
68 [*]volatile align(4) u8, [*]const volatile align(4) u8,
69 [*]align(8) u8, [*]const align(8) u8,
70 [*]volatile align(8) u8, [*]const volatile align(8) u8,
71 [*]allowzero u8, [*]const allowzero u8,
72 [*]volatile allowzero u8, [*]const volatile allowzero u8,
73 [*]align(4) allowzero u8, [*]const align(4) allowzero u8,
74 [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8,
65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]align(4) const u8,
68 [*]align(4) volatile u8, [*]align(4) const volatile u8,
69 [*]align(8) u8, [*]align(8) const u8,
70 [*]align(8) volatile u8, [*]align(8) const volatile u8,
71 [*]allowzero u8, [*]allowzero const u8,
72 [*]allowzero volatile u8, [*]allowzero const volatile u8,
73 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
74 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
7575 // Slice Types
76 []u8, []const u8,
77 []volatile u8, []const volatile u8,
78 []align(4) u8, []const align(4) u8,
79 []volatile align(4) u8, []const volatile align(4) u8,
80 []align(8) u8, []const align(8) u8,
81 []volatile align(8) u8, []const volatile align(8) u8,
82 []allowzero u8, []const allowzero u8,
83 []volatile allowzero u8, []const volatile allowzero u8,
84 []align(4) allowzero u8, []const align(4) allowzero u8,
85 []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8,
76 []u8, []const u8,
77 []volatile u8, []const volatile u8,
78 []align(4) u8, []align(4) const u8,
79 []align(4) volatile u8, []align(4) const volatile u8,
80 []align(8) u8, []align(8) const u8,
81 []align(8) volatile u8, []align(8) const volatile u8,
82 []allowzero u8, []allowzero const u8,
83 []allowzero volatile u8, []allowzero const volatile u8,
84 []allowzero align(4) u8, []allowzero align(4) const u8,
85 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
8686 // C Pointer Types
87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]const align(4) u8,
90 [*c]volatile align(4) u8, [*c]const volatile align(4) u8,
91 [*c]align(8) u8, [*c]const align(8) u8,
92 [*c]volatile align(8) u8, [*c]const volatile align(8) u8,
87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]align(4) const u8,
90 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
91 [*c]align(8) u8, [*c]align(8) const u8,
92 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
9393 });
9494}
9595
9696test "Type.Array" {
97 testing.expect([123]u8 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 123, .child = u8 } }));
98 testing.expect([2]u32 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 2, .child = u32 } }));
99 testTypes([_]type {[1]u8, [30]usize, [7]bool});
97 testing.expect([123]u8 == @Type(TypeInfo{
98 .Array = TypeInfo.Array{
99 .len = 123,
100 .child = u8,
101 .sentinel = null,
102 },
103 }));
104 testing.expect([2]u32 == @Type(TypeInfo{
105 .Array = TypeInfo.Array{
106 .len = 2,
107 .child = u32,
108 .sentinel = null,
109 },
110 }));
111 testing.expect([2:0]u32 == @Type(TypeInfo{
112 .Array = TypeInfo.Array{
113 .len = 2,
114 .child = u32,
115 .sentinel = 0,
116 },
117 }));
118 testTypes([_]type{ [1]u8, [30]usize, [7]bool });
100119}
101120
102121test "Type.ComptimeFloat" {
103 testTypes([_]type {comptime_float});
122 testTypes([_]type{comptime_float});
104123}
105124test "Type.ComptimeInt" {
106 testTypes([_]type {comptime_int});
125 testTypes([_]type{comptime_int});
107126}
108127test "Type.Undefined" {
109 testTypes([_]type {@typeOf(undefined)});
128 testTypes([_]type{@typeOf(undefined)});
110129}
111130test "Type.Null" {
112 testTypes([_]type {@typeOf(null)});
131 testTypes([_]type{@typeOf(null)});
113132}
test/stage1/behavior/type_info.zig+26-5
......@@ -46,6 +46,7 @@ fn testPointer() void {
4646 expect(u32_ptr_info.Pointer.is_volatile == false);
4747 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
4848 expect(u32_ptr_info.Pointer.child == u32);
49 expect(u32_ptr_info.Pointer.sentinel == null);
4950}
5051
5152test "type info: unknown length pointer type info" {
......@@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" {
5556
5657fn testUnknownLenPtr() void {
5758 const u32_ptr_info = @typeInfo([*]const volatile f64);
58 expect(@as(TypeId,u32_ptr_info) == TypeId.Pointer);
59 expect(@as(TypeId, u32_ptr_info) == TypeId.Pointer);
5960 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
6061 expect(u32_ptr_info.Pointer.is_const == true);
6162 expect(u32_ptr_info.Pointer.is_volatile == true);
63 expect(u32_ptr_info.Pointer.sentinel == null);
6264 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
6365 expect(u32_ptr_info.Pointer.child == f64);
6466}
6567
68test "type info: null terminated pointer type info" {
69 testNullTerminatedPtr();
70 comptime testNullTerminatedPtr();
71}
72
73fn testNullTerminatedPtr() void {
74 const ptr_info = @typeInfo([*:0]u8);
75 expect(@as(TypeId, ptr_info) == TypeId.Pointer);
76 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
77 expect(ptr_info.Pointer.is_const == false);
78 expect(ptr_info.Pointer.is_volatile == false);
79 expect(ptr_info.Pointer.sentinel.? == 0);
80
81 expect(@typeInfo([:0]u8).Pointer.sentinel != null);
82 expect(@typeInfo([10:0]u8).Array.sentinel != null);
83 expect(@typeInfo([10:0]u8).Array.len == 10);
84 expect(@sizeOf([10:0]u8) == 11);
85}
86
6687test "type info: C pointer type info" {
6788 testCPtr();
6889 comptime testCPtr();
......@@ -70,7 +91,7 @@ test "type info: C pointer type info" {
7091
7192fn testCPtr() void {
7293 const ptr_info = @typeInfo([*c]align(4) const i8);
73 expect(@as(TypeId,ptr_info) == TypeId.Pointer);
94 expect(@as(TypeId, ptr_info) == TypeId.Pointer);
7495 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
7596 expect(ptr_info.Pointer.is_const);
7697 expect(!ptr_info.Pointer.is_volatile);
......@@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" {
288309fn testAnyFrame() void {
289310 {
290311 const anyframe_info = @typeInfo(anyframe->i32);
291 expect(@as(TypeId,anyframe_info) == .AnyFrame);
312 expect(@as(TypeId, anyframe_info) == .AnyFrame);
292313 expect(anyframe_info.AnyFrame.child.? == i32);
293314 }
294315
295316 {
296317 const anyframe_info = @typeInfo(anyframe);
297 expect(@as(TypeId,anyframe_info) == .AnyFrame);
318 expect(@as(TypeId, anyframe_info) == .AnyFrame);
298319 expect(anyframe_info.AnyFrame.child == null);
299320 }
300321}
......@@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" {
334355 if (std.mem.eql(u8, decl.name, "bar1")) {
335356 expect(decl.data.Fn.lib_name == null);
336357 } else {
337 std.testing.expectEqual(@as([]const u8,"cool"), decl.data.Fn.lib_name.?);
358 std.testing.expectEqual(@as([]const u8, "cool"), decl.data.Fn.lib_name.?);
338359 }
339360 }
340361 }
test/stage1/c_abi/main.zig+1-1
......@@ -119,7 +119,7 @@ export fn zig_bool(x: bool) void {
119119extern fn c_array([10]u8) void;
120120
121121test "C ABI array" {
122 var array: [10]u8 = "1234567890";
122 var array: [10]u8 = "1234567890".*;
123123 c_array(array);
124124}
125125
test/stage2/compare_output.zig+2-2
......@@ -6,7 +6,7 @@ pub fn addCases(ctx: *TestContext) !void {
66 try ctx.testCompareOutputLibC(
77 \\extern fn puts([*]const u8) void;
88 \\export fn main() c_int {
9 \\ puts(c"Hello, world!");
9 \\ puts("Hello, world!");
1010 \\ return 0;
1111 \\}
1212 , "Hello, world!" ++ std.cstr.line_sep);
......@@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
1515 try ctx.testCompareOutputLibC(
1616 \\extern fn puts(s: [*]const u8) void;
1717 \\export fn main() c_int {
18 \\ return foo(c"OK");
18 \\ return foo("OK");
1919 \\}
2020 \\fn foo(s: [*]const u8) c_int {
2121 \\ puts(s);
test/standalone/hello_world/hello_libc.zig+1-1
......@@ -5,7 +5,7 @@ const c = @cImport({
55 @cInclude("string.h");
66});
77
8const msg = c"Hello, world!\n";
8const msg = "Hello, world!\n";
99
1010export fn main(argc: c_int, argv: **u8) c_int {
1111 if (c.printf(msg) != @intCast(c_int, c.strlen(msg))) return -1;
test/translate_c.zig+14-14
......@@ -47,7 +47,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
4747 \\pub fn foo() void {
4848 \\ var a: c_int = undefined;
4949 \\ _ = 1;
50 \\ _ = c"hey";
50 \\ _ = "hey";
5151 \\ _ = (1 + 1);
5252 \\ _ = (1 - 1);
5353 \\ a = 1;
......@@ -213,9 +213,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213213 \\}
214214 ,
215215 \\pub fn foo() void {
216 \\ _ = c"foo";
217 \\ _ = c"foo";
218 \\ _ = c"void foo(void)";
216 \\ _ = "foo";
217 \\ _ = "foo";
218 \\ _ = "void foo(void)";
219219 \\}
220220 );
221221
......@@ -232,7 +232,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
232232 \\pub fn foo() void {
233233 \\ var a: c_int = undefined;
234234 \\ _ = 1;
235 \\ _ = c"hey";
235 \\ _ = "hey";
236236 \\ _ = (1 + 1);
237237 \\ _ = (1 - 1);
238238 \\ a = 1;
......@@ -543,7 +543,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
543543 cases.add("#define string",
544544 \\#define foo "a string"
545545 ,
546 \\pub const foo = c"a string";
546 \\pub const foo = "a string";
547547 );
548548
549549 cases.add("__cdecl doesn't mess up function pointers",
......@@ -617,9 +617,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
617617 \\#define FOO2 "aoeu\x0007a derp"
618618 \\#define FOO_CHAR '\xfF'
619619 ,
620 \\pub const FOO = c"aoeu\xab derp";
620 \\pub const FOO = "aoeu\xab derp";
621621 ,
622 \\pub const FOO2 = c"aoeuz derp";
622 \\pub const FOO2 = "aoeuz derp";
623623 ,
624624 \\pub const FOO_CHAR = 255;
625625 );
......@@ -629,9 +629,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
629629 \\#define FOO2 "aoeu\0234 derp"
630630 \\#define FOO_CHAR '\077'
631631 ,
632 \\pub const FOO = c"aoeu\x13 derp";
632 \\pub const FOO = "aoeu\x13 derp";
633633 ,
634 \\pub const FOO2 = c"aoeu\x134 derp";
634 \\pub const FOO2 = "aoeu\x134 derp";
635635 ,
636636 \\pub const FOO_CHAR = 63;
637637 );
......@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
13511351 \\}
13521352 ,
13531353 \\pub fn foo() [*c]const u8 {
1354 \\ return c"bar";
1354 \\ return "bar";
13551355 \\}
13561356 );
13571357
......@@ -1523,7 +1523,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15231523 cases.add("const ptr initializer",
15241524 \\static const char *v0 = "0.0.0";
15251525 ,
1526 \\pub var v0: [*c]const u8 = c"0.0.0";
1526 \\pub var v0: [*c]const u8 = "0.0.0";
15271527 );
15281528
15291529 cases.add("static incomplete array inside function",
......@@ -1532,7 +1532,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
15321532 \\}
15331533 ,
15341534 \\pub fn foo() void {
1535 \\ const v2: [*c]const u8 = c"2.2.2";
1535 \\ const v2: [*c]const u8 = "2.2.2";
15361536 \\}
15371537 );
15381538
......@@ -1809,7 +1809,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
18091809 \\ var i: u8 = @as(u8, '\x0b');
18101810 \\ var j: u8 = @as(u8, '\x00');
18111811 \\ var k: u8 = @as(u8, '\"');
1812 \\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
1812 \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
18131813 \\}
18141814 \\
18151815 );