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...@@ -954,8 +954,6 @@ fn tokenizeAndPrintRaw(docgen_tokenizer: *Tokenizer, out: var, source_token: Tok
954 .AngleBracketAngleBracketRight,954 .AngleBracketAngleBracketRight,
955 .AngleBracketAngleBracketRightEqual,955 .AngleBracketAngleBracketRightEqual,
956 .Tilde,956 .Tilde,
957 .BracketStarBracket,
958 .BracketStarCBracket,
959 => try writeEscaped(out, src[token.start..token.end]),957 => try writeEscaped(out, src[token.start..token.end]),
960958
961 .Invalid, .Invalid_ampersands => return parseError(959 .Invalid, .Invalid_ampersands => return parseError(
doc/langref.html.in+89-59
...@@ -546,7 +546,11 @@ pub fn main() void {...@@ -546,7 +546,11 @@ pub fn main() void {
546 {#header_close#}546 {#header_close#}
547 {#header_open|String Literals and Character Literals#}547 {#header_open|String Literals and Character Literals#}
548 <p>548 <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#}.
550 </p>554 </p>
551 <p>555 <p>
552 Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as556 Character literals have type {#syntax#}comptime_int{#endsyntax#}, the same as
...@@ -558,20 +562,15 @@ const assert = @import("std").debug.assert;...@@ -558,20 +562,15 @@ const assert = @import("std").debug.assert;
558const mem = @import("std").mem;562const mem = @import("std").mem;
559563
560test "string literals" {564test "string literals" {
561 // In Zig a string literal is an array of bytes.565 const bytes = "hello";
562 const normal_bytes = "hello";566 assert(@typeOf(bytes) == *const [5:0]u8);
563 assert(@typeOf(normal_bytes) == [5]u8);567 assert(bytes.len == 5);
564 assert(normal_bytes.len == 5);568 assert(bytes[1] == 'e');
565 assert(normal_bytes[1] == 'e');569 assert(bytes[5] == 0);
566 assert('e' == '\x65');570 assert('e' == '\x65');
567 assert('\u{1f4a9}' == 128169);571 assert('\u{1f4a9}' == 128169);
568 assert('💯' == 128175);572 assert('💯' == 128175);
569 assert(mem.eql(u8, "hello", "h\x65llo"));573 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);
575}574}
576 {#code_end#}575 {#code_end#}
577 {#see_also|Arrays|Zig Test|Source Encoding#}576 {#see_also|Arrays|Zig Test|Source Encoding#}
...@@ -641,23 +640,6 @@ const hello_world_in_c =...@@ -641,23 +640,6 @@ const hello_world_in_c =
641 \\}640 \\}
642;641;
643 {#code_end#}642 {#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>
661 {#see_also|@embedFile#}643 {#see_also|@embedFile#}
662 {#header_close#}644 {#header_close#}
663 {#header_close#}645 {#header_close#}
...@@ -1638,12 +1620,11 @@ comptime {...@@ -1638,12 +1620,11 @@ comptime {
1638 assert(message.len == 5);1620 assert(message.len == 5);
1639}1621}
16401622
1641// a string literal is an array literal1623// A string literal is a pointer to an array literal.
1642const same_message = "hello";1624const same_message = "hello".*;
16431625
1644comptime {1626comptime {
1645 assert(mem.eql(u8, message, same_message));1627 assert(mem.eql(u8, message, same_message));
1646 assert(@typeOf(message) == @typeOf(same_message));
1647}1628}
16481629
1649test "iterate over an array" {1630test "iterate over an array" {
...@@ -1799,6 +1780,26 @@ test "multidimensional arrays" {...@@ -1799,6 +1780,26 @@ test "multidimensional arrays" {
1799}1780}
1800 {#code_end#}1781 {#code_end#}
1801 {#header_close#}1782 {#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#}
1802 {#header_close#}1803 {#header_close#}
18031804
1804 {#header_open|Vectors#}1805 {#header_open|Vectors#}
...@@ -1899,7 +1900,7 @@ test "pointer array access" {...@@ -1899,7 +1900,7 @@ test "pointer array access" {
1899}1900}
1900 {#code_end#}1901 {#code_end#}
1901 <p>1902 <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#}.
1903 You can turn an array or pointer into a slice using slice syntax.1904 You can turn an array or pointer into a slice using slice syntax.
1904 </p>1905 </p>
1905 <p>1906 <p>
...@@ -2111,6 +2112,29 @@ test "allowzero" {...@@ -2111,6 +2112,29 @@ test "allowzero" {
2111}2112}
2112 {#code_end#}2113 {#code_end#}
2113 {#header_close#}2114 {#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#}
2114 {#header_close#}2138 {#header_close#}
21152139
2116 {#header_open|Slices#}2140 {#header_open|Slices#}
...@@ -2194,7 +2218,29 @@ test "slice widening" {...@@ -2194,7 +2218,29 @@ test "slice widening" {
2194}2218}
2195 {#code_end#}2219 {#code_end#}
2196 {#see_also|Pointers|for|Arrays#}2220 {#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#}
2197 {#header_close#}2241 {#header_close#}
2242 {#header_close#}
2243
2198 {#header_open|struct#}2244 {#header_open|struct#}
2199 {#code_begin|test|structs#}2245 {#code_begin|test|structs#}
2200// Declare a struct.2246// Declare a struct.
...@@ -4817,9 +4863,9 @@ const assert = std.debug.assert;...@@ -4817,9 +4863,9 @@ const assert = std.debug.assert;
4817const mem = std.mem;4863const mem = std.mem;
48184864
4819test "cast *[1][*]const u8 to [*]const ?[*]const u8" {4865test "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"};
4821 const x: [*]const ?[*]const u8 = &window_name;4867 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"));
4823}4869}
4824 {#code_end#}4870 {#code_end#}
4825 {#header_close#}4871 {#header_close#}
...@@ -4859,7 +4905,7 @@ test "float widening" {...@@ -4859,7 +4905,7 @@ test "float widening" {
4859 {#code_end#}4905 {#code_end#}
4860 {#header_close#}4906 {#header_close#}
4861 {#header_open|Type Coercion: Arrays and Pointers#}4907 {#header_open|Type Coercion: Arrays and Pointers#}
4862 {#code_begin|test#}4908 {#code_begin|test|coerce_arrays_and_ptrs#}
4863const std = @import("std");4909const std = @import("std");
4864const assert = std.debug.assert;4910const assert = std.debug.assert;
48654911
...@@ -4898,7 +4944,7 @@ test "[N]T to ?[]const T" {...@@ -4898,7 +4944,7 @@ test "[N]T to ?[]const T" {
48984944
4899// In this cast, the array length becomes the slice length.4945// In this cast, the array length becomes the slice length.
4900test "*[N]T to []T" {4946test "*[N]T to []T" {
4901 var buf: [5]u8 = "hello";4947 var buf: [5]u8 = "hello".*;
4902 const x: []u8 = &buf;4948 const x: []u8 = &buf;
4903 assert(std.mem.eql(u8, x, "hello"));4949 assert(std.mem.eql(u8, x, "hello"));
49044950
...@@ -4910,7 +4956,7 @@ test "*[N]T to []T" {...@@ -4910,7 +4956,7 @@ test "*[N]T to []T" {
4910// Single-item pointers to arrays can be coerced to4956// Single-item pointers to arrays can be coerced to
4911// unknown length pointers.4957// unknown length pointers.
4912test "*[N]T to [*]T" {4958test "*[N]T to [*]T" {
4913 var buf: [5]u8 = "hello";4959 var buf: [5]u8 = "hello".*;
4914 const x: [*]u8 = &buf;4960 const x: [*]u8 = &buf;
4915 assert(x[4] == 'o');4961 assert(x[4] == 'o');
4916 // x[5] would be an uncaught out of bounds pointer dereference!4962 // x[5] would be an uncaught out of bounds pointer dereference!
...@@ -4918,7 +4964,7 @@ test "*[N]T to [*]T" {...@@ -4918,7 +4964,7 @@ test "*[N]T to [*]T" {
49184964
4919// Likewise, it works when the destination type is an optional.4965// Likewise, it works when the destination type is an optional.
4920test "*[N]T to ?[*]T" {4966test "*[N]T to ?[*]T" {
4921 var buf: [5]u8 = "hello";4967 var buf: [5]u8 = "hello".*;
4922 const x: ?[*]u8 = &buf;4968 const x: ?[*]u8 = &buf;
4923 assert(x.?[4] == 'o');4969 assert(x.?[4] == 'o');
4924}4970}
...@@ -5089,7 +5135,7 @@ test "coercion of zero bit types" {...@@ -5089,7 +5135,7 @@ test "coercion of zero bit types" {
5089 This kind of type resolution chooses a type that all peer types can coerce into. Here are5135 This kind of type resolution chooses a type that all peer types can coerce into. Here are
5090 some examples:5136 some examples:
5091 </p>5137 </p>
5092 {#code_begin|test#}5138 {#code_begin|test|peer_type_resolution#}
5093const std = @import("std");5139const std = @import("std");
5094const assert = std.debug.assert;5140const assert = std.debug.assert;
5095const mem = std.mem;5141const mem = std.mem;
...@@ -5156,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {...@@ -5156,13 +5202,13 @@ fn peerTypeEmptyArrayAndSlice(a: bool, slice: []const u8) []const u8 {
5156}5202}
5157test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {5203test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
5158 {5204 {
5159 var data = "hi";5205 var data = "hi".*;
5160 const slice = data[0..];5206 const slice = data[0..];
5161 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);5207 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
5162 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);5208 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
5163 }5209 }
5164 comptime {5210 comptime {
5165 var data = "hi";5211 var data = "hi".*;
5166 const slice = data[0..];5212 const slice = data[0..];
5167 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);5213 assert((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
5168 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);5214 assert((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
...@@ -8627,7 +8673,7 @@ pub fn main() void {...@@ -8627,7 +8673,7 @@ pub fn main() void {
8627 <p>At compile-time:</p>8673 <p>At compile-time:</p>
8628 {#code_begin|test_err|index 5 outside array of size 5#}8674 {#code_begin|test_err|index 5 outside array of size 5#}
8629comptime {8675comptime {
8630 const array = "hello";8676 const array: [5]u8 = "hello".*;
8631 const garbage = array[5];8677 const garbage = array[5];
8632}8678}
8633 {#code_end#}8679 {#code_end#}
...@@ -9603,22 +9649,6 @@ test "assert in release fast mode" {...@@ -9603,22 +9649,6 @@ test "assert in release fast mode" {
9603 </ul>9649 </ul>
9604 {#see_also|Primitive Types#}9650 {#see_also|Primitive Types#}
9605 {#header_close#}9651 {#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
9623 {#header_open|Import from C Header File#}9653 {#header_open|Import from C Header File#}
9624 <p>9654 <p>
...@@ -9633,7 +9663,7 @@ const c = @cImport({...@@ -9633,7 +9663,7 @@ const c = @cImport({
9633 @cInclude("stdio.h");9663 @cInclude("stdio.h");
9634});9664});
9635pub fn main() void {9665pub fn main() void {
9636 _ = c.printf(c"hello\n");9666 _ = c.printf("hello\n");
9637}9667}
9638 {#code_end#}9668 {#code_end#}
9639 <p>9669 <p>
lib/std/buffer.zig+2-7
...@@ -72,11 +72,11 @@ pub const Buffer = struct {...@@ -72,11 +72,11 @@ pub const Buffer = struct {
72 self.list.deinit();72 self.list.deinit();
73 }73 }
7474
75 pub fn toSlice(self: Buffer) []u8 {75 pub fn toSlice(self: Buffer) [:0]u8 {
76 return self.list.toSlice()[0..self.len()];76 return self.list.toSlice()[0..self.len()];
77 }77 }
7878
79 pub fn toSliceConst(self: Buffer) []const u8 {79 pub fn toSliceConst(self: Buffer) [:0]const u8 {
80 return self.list.toSliceConst()[0..self.len()];80 return self.list.toSliceConst()[0..self.len()];
81 }81 }
8282
...@@ -131,11 +131,6 @@ pub const Buffer = struct {...@@ -131,11 +131,6 @@ pub const Buffer = struct {
131 try self.resize(m.len);131 try self.resize(m.len);
132 mem.copy(u8, self.list.toSlice(), m);132 mem.copy(u8, self.list.toSlice(), m);
133 }133 }
134
135 /// For passing to C functions.
136 pub fn ptr(self: Buffer) [*]u8 {
137 return self.list.items.ptr;
138 }
139};134};
140135
141test "simple Buffer" {136test "simple Buffer" {
lib/std/builtin.zig+8
...@@ -144,6 +144,10 @@ pub const TypeInfo = union(enum) {...@@ -144,6 +144,10 @@ pub const TypeInfo = union(enum) {
144 alignment: comptime_int,144 alignment: comptime_int,
145 child: type,145 child: type,
146 is_allowzero: bool,146 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
148 /// This data structure is used by the Zig language code generation and152 /// This data structure is used by the Zig language code generation and
149 /// therefore must be kept in sync with the compiler implementation.153 /// therefore must be kept in sync with the compiler implementation.
...@@ -160,6 +164,10 @@ pub const TypeInfo = union(enum) {...@@ -160,6 +164,10 @@ pub const TypeInfo = union(enum) {
160 pub const Array = struct {164 pub const Array = struct {
161 len: comptime_int,165 len: comptime_int,
162 child: type,166 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,
163 };171 };
164172
165 /// This data structure is used by the Zig language code generation and173 /// 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;...@@ -63,7 +63,7 @@ pub extern "c" fn fclose(stream: *FILE) c_int;
63pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;63pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;
64pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize;64pub 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;
67pub extern "c" fn abort() noreturn;67pub extern "c" fn abort() noreturn;
68pub extern "c" fn exit(code: c_int) noreturn;68pub extern "c" fn exit(code: c_int) noreturn;
69pub extern "c" fn isatty(fd: fd_t) c_int;69pub 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: [...@@ -102,7 +102,7 @@ pub extern "c" fn execve(path: [*]const u8, argv: [*]const ?[*]const u8, envp: [
102pub extern "c" fn dup(fd: fd_t) c_int;102pub extern "c" fn dup(fd: fd_t) c_int;
103pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;103pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int;
104pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize;104pub 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;
106pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;106pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int;
107pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;107pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int;
108pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int;108pub 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;...@@ -110,7 +110,7 @@ pub extern "c" fn nanosleep(rqtp: *const timespec, rmtp: ?*timespec) c_int;
110pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;110pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int;
111pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;111pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int;
112pub extern "c" fn rmdir(path: [*]const u8) c_int;112pub 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;
114pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;114pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
115pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;115pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int;
116pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int;116pub 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 {...@@ -330,7 +330,7 @@ pub const ChildProcess = struct {
330330
331 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);331 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
332 const dev_null_fd = if (any_ignore)332 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) {
334 error.PathAlreadyExists => unreachable,334 error.PathAlreadyExists => unreachable,
335 error.NoSpaceLeft => unreachable,335 error.NoSpaceLeft => unreachable,
336 error.FileTooBig => unreachable,336 error.FileTooBig => unreachable,
...@@ -441,6 +441,7 @@ pub const ChildProcess = struct {...@@ -441,6 +441,7 @@ pub const ChildProcess = struct {
441441
442 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);442 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
444 const nul_handle = if (any_ignore)445 const nul_handle = if (any_ignore)
445 windows.CreateFile(446 windows.CreateFile(
446 "NUL",447 "NUL",
lib/std/crypto/x25519.zig+6-6
...@@ -610,8 +610,8 @@ test "x25519 rfc7748 vector2" {...@@ -610,8 +610,8 @@ test "x25519 rfc7748 vector2" {
610}610}
611611
612test "x25519 rfc7748 one iteration" {612test "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";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";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
616 var k: [32]u8 = initial_value;616 var k: [32]u8 = initial_value;
617 var u: [32]u8 = initial_value;617 var u: [32]u8 = initial_value;
...@@ -634,8 +634,8 @@ test "x25519 rfc7748 1,000 iterations" {...@@ -634,8 +634,8 @@ test "x25519 rfc7748 1,000 iterations" {
634 return error.SkipZigTest;634 return error.SkipZigTest;
635 }635 }
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";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";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
640 var k: [32]u8 = initial_value;640 var k: [32]u8 = initial_value;
641 var u: [32]u8 = initial_value;641 var u: [32]u8 = initial_value;
...@@ -657,8 +657,8 @@ test "x25519 rfc7748 1,000,000 iterations" {...@@ -657,8 +657,8 @@ test "x25519 rfc7748 1,000,000 iterations" {
657 return error.SkipZigTest;657 return error.SkipZigTest;
658 }658 }
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";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";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
663 var k: [32]u8 = initial_value;663 var k: [32]u8 = initial_value;
664 var u: [32]u8 = initial_value;664 var u: [32]u8 = initial_value;
lib/std/cstr.zig+2-2
...@@ -27,8 +27,8 @@ test "cstr fns" {...@@ -27,8 +27,8 @@ test "cstr fns" {
27}27}
2828
29fn testCStrFnsImpl() void {29fn testCStrFnsImpl() void {
30 testing.expect(cmp(c"aoeu", c"aoez") == -1);30 testing.expect(cmp("aoeu", "aoez") == -1);
31 testing.expect(mem.len(u8, c"123456789") == 9);31 testing.expect(mem.len(u8, "123456789") == 9);
32}32}
3333
34/// Returns a mutable slice with 1 more byte of length which is a null byte.34/// 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...@@ -401,7 +401,7 @@ fn printSourceAtAddressWindows(di: *DebugInfo, out_stream: var, relocated_addres
401 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;401 const vaddr_start = coff_section.header.virtual_address + proc_sym.CodeOffset;
402 const vaddr_end = vaddr_start + proc_sym.CodeSize;402 const vaddr_end = vaddr_start + proc_sym.CodeSize;
403 if (relative_address >= vaddr_start and relative_address < vaddr_end) {403 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));
405 }405 }
406 },406 },
407 else => {},407 else => {},
...@@ -703,9 +703,9 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt...@@ -703,9 +703,9 @@ fn printSourceAtAddressMacOs(di: *DebugInfo, out_stream: var, address: usize, tt
703 return;703 return;
704 };704 };
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));
707 const compile_unit_name = if (symbol.ofile) |ofile| blk: {707 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));
709 break :blk fs.path.basename(ofile_path);709 break :blk fs.path.basename(ofile_path);
710 } else "???";710 } else "???";
711 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {711 if (getLineNumberInfoMacOs(di, symbol.*, adjusted_addr)) |line_info| {
...@@ -915,7 +915,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {...@@ -915,7 +915,7 @@ fn openSelfDebugInfoWindows(allocator: *mem.Allocator) !DebugInfo {
915 for (present) |_| {915 for (present) |_| {
916 const name_offset = try pdb_stream.stream.readIntLittle(u32);916 const name_offset = try pdb_stream.stream.readIntLittle(u32);
917 const name_index = try pdb_stream.stream.readIntLittle(u32);917 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));
919 if (mem.eql(u8, name, "/names")) {919 if (mem.eql(u8, name, "/names")) {
920 break :str_tab_index name_index;920 break :str_tab_index name_index;
921 }921 }
...@@ -1708,7 +1708,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1708,7 +1708,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1708 const gop = try di.ofiles.getOrPut(ofile);1708 const gop = try di.ofiles.getOrPut(ofile);
1709 const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {1709 const mach_o_file = if (gop.found_existing) &gop.kv.value else blk: {
1710 errdefer _ = di.ofiles.remove(ofile);1710 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
1713 gop.kv.value = MachOFile{1713 gop.kv.value = MachOFile{
1714 .bytes = try std.fs.Dir.cwd().readFileAllocAligned(1714 .bytes = try std.fs.Dir.cwd().readFileAllocAligned(
...@@ -1741,7 +1741,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u...@@ -1741,7 +1741,7 @@ fn getLineNumberInfoMacOs(di: *DebugInfo, symbol: MachoSymbol, target_address: u
1741 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and1741 if (sect.flags & macho.SECTION_TYPE == macho.S_REGULAR and
1742 (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)1742 (sect.flags & macho.SECTION_ATTRIBUTES) & macho.S_ATTR_DEBUG == macho.S_ATTR_DEBUG)
1743 {1743 {
1744 const sect_name = mem.toSliceConst(u8, &sect.sectname);1744 const sect_name = mem.toSliceConst(u8, @ptrCast([*:0]const u8, &sect.sectname));
1745 if (mem.eql(u8, sect_name, "__debug_line")) {1745 if (mem.eql(u8, sect_name, "__debug_line")) {
1746 gop.kv.value.sect_debug_line = sect;1746 gop.kv.value.sect_debug_line = sect;
1747 } else if (mem.eql(u8, sect_name, "__debug_info")) {1747 } else if (mem.eql(u8, sect_name, "__debug_info")) {
...@@ -2323,8 +2323,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {...@@ -2323,8 +2323,8 @@ fn readInitialLengthMem(ptr: *[*]const u8, is_64: *bool) !u64 {
2323 }2323 }
2324}2324}
23252325
2326fn readStringMem(ptr: *[*]const u8) []const u8 {2326fn readStringMem(ptr: *[*]const u8) [:0]const u8 {
2327 const result = mem.toSliceConst(u8, ptr.*);2327 const result = mem.toSliceConst(u8, @ptrCast([*:0]const u8, ptr.*));
2328 ptr.* += result.len + 1;2328 ptr.* += result.len + 1;
2329 return result;2329 return result;
2330}2330}
lib/std/dynamic_library.zig+4-4
...@@ -140,7 +140,7 @@ pub const LinuxDynLib = struct {...@@ -140,7 +140,7 @@ pub const LinuxDynLib = struct {
140};140};
141141
142pub const ElfLib = struct {142pub const ElfLib = struct {
143 strings: [*]u8,143 strings: [*:0]u8,
144 syms: [*]elf.Sym,144 syms: [*]elf.Sym,
145 hashtab: [*]os.Elf_Symndx,145 hashtab: [*]os.Elf_Symndx,
146 versym: ?[*]u16,146 versym: ?[*]u16,
...@@ -175,7 +175,7 @@ pub const ElfLib = struct {...@@ -175,7 +175,7 @@ pub const ElfLib = struct {
175 const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;175 const dynv = maybe_dynv orelse return error.MissingDynamicLinkingInformation;
176 if (base == maxInt(usize)) return error.BaseNotFound;176 if (base == maxInt(usize)) return error.BaseNotFound;
177177
178 var maybe_strings: ?[*]u8 = null;178 var maybe_strings: ?[*:0]u8 = null;
179 var maybe_syms: ?[*]elf.Sym = null;179 var maybe_syms: ?[*]elf.Sym = null;
180 var maybe_hashtab: ?[*]os.Elf_Symndx = null;180 var maybe_hashtab: ?[*]os.Elf_Symndx = null;
181 var maybe_versym: ?[*]u16 = null;181 var maybe_versym: ?[*]u16 = null;
...@@ -186,7 +186,7 @@ pub const ElfLib = struct {...@@ -186,7 +186,7 @@ pub const ElfLib = struct {
186 while (dynv[i] != 0) : (i += 2) {186 while (dynv[i] != 0) : (i += 2) {
187 const p = base + dynv[i + 1];187 const p = base + dynv[i + 1];
188 switch (dynv[i]) {188 switch (dynv[i]) {
189 elf.DT_STRTAB => maybe_strings = @intToPtr([*]u8, p),189 elf.DT_STRTAB => maybe_strings = @intToPtr([*:0]u8, p),
190 elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),190 elf.DT_SYMTAB => maybe_syms = @intToPtr([*]elf.Sym, p),
191 elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),191 elf.DT_HASH => maybe_hashtab = @intToPtr([*]os.Elf_Symndx, p),
192 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),192 elf.DT_VERSYM => maybe_versym = @intToPtr([*]u16, p),
...@@ -230,7 +230,7 @@ pub const ElfLib = struct {...@@ -230,7 +230,7 @@ pub const ElfLib = struct {
230 }230 }
231};231};
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 {
234 var def = def_arg;234 var def = def_arg;
235 const vsym = @bitCast(u32, vsym_arg) & 0x7fff;235 const vsym = @bitCast(u32, vsym_arg) & 0x7fff;
236 while (true) {236 while (true) {
lib/std/event/fs.zig+2-4
...@@ -58,8 +58,7 @@ pub const Request = struct {...@@ -58,8 +58,7 @@ pub const Request = struct {
58 };58 };
5959
60 pub const Open = struct {60 pub const Open = struct {
61 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/26561 path: [:0]const u8,
62 path: []const u8,
63 flags: u32,62 flags: u32,
64 mode: File.Mode,63 mode: File.Mode,
65 result: Error!fd_t,64 result: Error!fd_t,
...@@ -68,8 +67,7 @@ pub const Request = struct {...@@ -68,8 +67,7 @@ pub const Request = struct {
68 };67 };
6968
70 pub const WriteFile = struct {69 pub const WriteFile = struct {
71 /// must be null terminated. TODO https://github.com/ziglang/zig/issues/26570 path: [:0]const u8,
72 path: []const u8,
73 contents: []const u8,71 contents: []const u8,
74 mode: File.Mode,72 mode: File.Mode,
75 result: Error!void,73 result: Error!void,
lib/std/fmt.zig+55-57
...@@ -1,8 +1,6 @@...@@ -1,8 +1,6 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const math = std.math;2const math = std.math;
3const debug = std.debug;3const assert = std.debug.assert;
4const assert = debug.assert;
5const testing = std.testing;
6const mem = std.mem;4const mem = std.mem;
7const builtin = @import("builtin");5const builtin = @import("builtin");
8const errol = @import("fmt/errol.zig");6const errol = @import("fmt/errol.zig");
...@@ -36,7 +34,7 @@ fn nextArg(comptime used_pos_args: *u32, comptime maybe_pos_arg: ?comptime_int,...@@ -36,7 +34,7 @@ fn nextArg(comptime used_pos_args: *u32, comptime maybe_pos_arg: ?comptime_int,
3634
37fn peekIsAlign(comptime fmt: []const u8) bool {35fn peekIsAlign(comptime fmt: []const u8) bool {
38 // Should only be called during a state transition to the format segment.36 // Should only be called during a state transition to the format segment.
39 std.debug.assert(fmt[0] == ':');37 comptime assert(fmt[0] == ':');
4038
41 inline for (([_]u8{ 1, 2 })[0..]) |i| {39 inline for (([_]u8{ 1, 2 })[0..]) |i| {
42 if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[i] == '>')) {40 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 {...@@ -1009,13 +1007,13 @@ pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
1009}1007}
10101008
1011test "parseInt" {1009test "parseInt" {
1012 testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);1010 std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
1013 testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);1011 std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
1014 testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);1012 std.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);1013 std.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);1014 std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
1017 testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);1015 std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
1018 testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);1016 std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
1019}1017}
10201018
1021const ParseUnsignedError = error{1019const ParseUnsignedError = error{
...@@ -1040,30 +1038,30 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned...@@ -1040,30 +1038,30 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
1040}1038}
10411039
1042test "parseUnsigned" {1040test "parseUnsigned" {
1043 testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);1041 std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
1044 testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);1042 std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
1045 testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));1043 std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
10461044
1047 testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);1045 std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
1048 testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));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);1050 std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
1053 testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);1051 std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
10541052
1055 testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));1053 std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
1056 testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));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
1060 // these numbers should fit even though the radix itself doesn't fit in the destination type1058 // 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);1059 std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
1062 testing.expect((try parseUnsigned(u1, "1", 10)) == 1);1060 std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
1063 testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));1061 std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
1064 testing.expect((try parseUnsigned(u1, "001", 16)) == 1);1062 std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
1065 testing.expect((try parseUnsigned(u2, "3", 16)) == 3);1063 std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
1066 testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));1064 std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
1067}1065}
10681066
1069pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;1067pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
...@@ -1134,19 +1132,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {...@@ -1134,19 +1132,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
1134test "bufPrintInt" {1132test "bufPrintInt" {
1135 var buffer: [100]u8 = undefined;1133 var buffer: [100]u8 = undefined;
1136 const buf = buffer[0..];1134 const buf = buffer[0..];
1137 testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110"));1135 std.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"));1136 std.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"));1137 std.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"));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"));1142 std.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"));1143 std.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"));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"));1146 std.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"));1147 std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42"));
1150}1148}
11511149
1152fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {1150fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
...@@ -1163,7 +1161,7 @@ test "parse u64 digit too big" {...@@ -1163,7 +1161,7 @@ test "parse u64 digit too big" {
11631161
1164test "parse unsigned comptime" {1162test "parse unsigned comptime" {
1165 comptime {1163 comptime {
1166 testing.expect((try parseUnsigned(usize, "2", 10)) == 2);1164 std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
1167 }1165 }
1168}1166}
11691167
...@@ -1218,23 +1216,23 @@ test "buffer" {...@@ -1218,23 +1216,23 @@ test "buffer" {
1218 var context = BufPrintContext{ .remaining = buf1[0..] };1216 var context = BufPrintContext{ .remaining = buf1[0..] };
1219 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1217 try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1220 var res = buf1[0 .. buf1.len - context.remaining.len];1218 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
1223 context = BufPrintContext{ .remaining = buf1[0..] };1221 context = BufPrintContext{ .remaining = buf1[0..] };
1224 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1222 try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1225 res = buf1[0 .. buf1.len - context.remaining.len];1223 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
1228 context = BufPrintContext{ .remaining = buf1[0..] };1226 context = BufPrintContext{ .remaining = buf1[0..] };
1229 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);1227 try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
1230 res = buf1[0 .. buf1.len - context.remaining.len];1228 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"));
1232 }1230 }
1233}1231}
12341232
1235test "array" {1233test "array" {
1236 {1234 {
1237 const value: [3]u8 = "abc";1235 const value: [3]u8 = "abc".*;
1238 try testFmt("array: abc\n", "array: {}\n", value);1236 try testFmt("array: abc\n", "array: {}\n", value);
1239 try testFmt("array: abc\n", "array: {}\n", &value);1237 try testFmt("array: abc\n", "array: {}\n", &value);
12401238
...@@ -1278,8 +1276,8 @@ test "pointer" {...@@ -1278,8 +1276,8 @@ test "pointer" {
1278}1276}
12791277
1280test "cstr" {1278test "cstr" {
1281 try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");1279 try testFmt("cstr: Test C\n", "cstr: {s}\n", "Test C");
1282 try testFmt("cstr: Test C \n", "cstr: {s:10}\n", c"Test C");1280 try testFmt("cstr: Test C \n", "cstr: {s:10}\n", "Test C");
1283}1281}
12841282
1285test "filesize" {1283test "filesize" {
...@@ -1479,10 +1477,10 @@ test "union" {...@@ -1479,10 +1477,10 @@ test "union" {
14791477
1480 var buf: [100]u8 = undefined;1478 var buf: [100]u8 = undefined;
1481 const uu_result = try bufPrint(buf[0..], "{}", uu_inst);1479 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
1484 const eu_result = try bufPrint(buf[0..], "{}", eu_inst);1482 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@"));
1486}1484}
14871485
1488test "enum" {1486test "enum" {
...@@ -1569,11 +1567,11 @@ pub fn trim(buf: []const u8) []const u8 {...@@ -1569,11 +1567,11 @@ pub fn trim(buf: []const u8) []const u8 {
1569}1567}
15701568
1571test "trim" {1569test "trim" {
1572 testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));1570 std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
1573 testing.expect(mem.eql(u8, "", trim(" ")));1571 std.testing.expect(mem.eql(u8, "", trim(" ")));
1574 testing.expect(mem.eql(u8, "", trim("")));1572 std.testing.expect(mem.eql(u8, "", trim("")));
1575 testing.expect(mem.eql(u8, "abc", trim(" abc")));1573 std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
1576 testing.expect(mem.eql(u8, "abc", trim("abc ")));1574 std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
1577}1575}
15781576
1579pub fn isWhiteSpace(byte: u8) bool {1577pub fn isWhiteSpace(byte: u8) bool {
...@@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" {...@@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" {
16071605
1608 var buf = try std.Buffer.init(std.debug.global_allocator, "");1606 var buf = try std.Buffer.init(std.debug.global_allocator, "");
1609 try formatIntValue(value, "", FormatOptions{}, &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);1607 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"));
1611}1609}
16121610
1613test "formatType max_depth" {1611test "formatType max_depth" {
...@@ -1661,19 +1659,19 @@ test "formatType max_depth" {...@@ -1661,19 +1659,19 @@ test "formatType max_depth" {
16611659
1662 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");1660 var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
1663 try formatType(inst, "", FormatOptions{}, &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);1661 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
1666 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");1664 var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
1667 try formatType(inst, "", FormatOptions{}, &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);1665 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
1670 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");1668 var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
1671 try formatType(inst, "", FormatOptions{}, &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);1669 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
1674 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");1672 var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
1675 try formatType(inst, "", FormatOptions{}, &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);1673 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) }"));
1677}1675}
16781676
1679test "positional" {1677test "positional" {
lib/std/fs.zig+29-27
...@@ -28,6 +28,7 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE...@@ -28,6 +28,7 @@ pub const GetAppDataDirError = @import("fs/get_app_data_dir.zig").GetAppDataDirE
28/// This represents the maximum size of a UTF-8 encoded file path.28/// This represents the maximum size of a UTF-8 encoded file path.
29/// All file system operations which return a path are guaranteed to29/// All file system operations which return a path are guaranteed to
30/// fit into a UTF-8 encoded array of this length.30/// fit into a UTF-8 encoded array of this length.
31/// The byte count includes room for a null sentinel byte.
31pub const MAX_PATH_BYTES = switch (builtin.os) {32pub const MAX_PATH_BYTES = switch (builtin.os) {
32 .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,33 .linux, .macosx, .ios, .freebsd, .netbsd, .dragonfly => os.PATH_MAX,
33 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.34 // Each UTF-16LE character may be expanded to 3 UTF-8 bytes.
...@@ -227,7 +228,7 @@ pub const AtomicFile = struct {...@@ -227,7 +228,7 @@ pub const AtomicFile = struct {
227 try crypto.randomBytes(rand_buf[0..]);228 try crypto.randomBytes(rand_buf[0..]);
228 b64_fs_encoder.encode(tmp_path_buf[dirname_component_len..tmp_path_len], rand_buf);229 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) {
231 error.PathAlreadyExists => continue,232 error.PathAlreadyExists => continue,
232 // TODO zig should figure out that this error set does not include PathAlreadyExists since233 // TODO zig should figure out that this error set does not include PathAlreadyExists since
233 // it is handled in the above switch234 // it is handled in the above switch
...@@ -247,7 +248,7 @@ pub const AtomicFile = struct {...@@ -247,7 +248,7 @@ pub const AtomicFile = struct {
247 pub fn deinit(self: *AtomicFile) void {248 pub fn deinit(self: *AtomicFile) void {
248 if (!self.finished) {249 if (!self.finished) {
249 self.file.close();250 self.file.close();
250 deleteFileC(&self.tmp_path_buf) catch {};251 deleteFileC(@ptrCast([*:0]u8, &self.tmp_path_buf)) catch {};
251 self.finished = true;252 self.finished = true;
252 }253 }
253 }254 }
...@@ -258,11 +259,11 @@ pub const AtomicFile = struct {...@@ -258,11 +259,11 @@ pub const AtomicFile = struct {
258 self.finished = true;259 self.finished = true;
259 if (builtin.os == .windows) {260 if (builtin.os == .windows) {
260 const dest_path_w = try os.windows.sliceToPrefixedFileW(self.dest_path);261 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));
262 return os.renameW(&tmp_path_w, &dest_path_w);263 return os.renameW(&tmp_path_w, &dest_path_w);
263 }264 }
264 const dest_path_c = try os.toPosixPath(self.dest_path);265 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);
266 }267 }
267};268};
268269
...@@ -274,12 +275,12 @@ pub fn makeDir(dir_path: []const u8) !void {...@@ -274,12 +275,12 @@ pub fn makeDir(dir_path: []const u8) !void {
274}275}
275276
276/// Same as `makeDir` except the parameter is a null-terminated UTF8-encoded string.277/// 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 {
278 return os.mkdirC(dir_path, default_new_dir_mode);279 return os.mkdirC(dir_path, default_new_dir_mode);
279}280}
280281
281/// Same as `makeDir` except the parameter is a null-terminated UTF16LE-encoded string.282/// 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 {
283 return os.mkdirW(dir_path, default_new_dir_mode);284 return os.mkdirW(dir_path, default_new_dir_mode);
284}285}
285286
...@@ -327,12 +328,12 @@ pub fn deleteDir(dir_path: []const u8) !void {...@@ -327,12 +328,12 @@ pub fn deleteDir(dir_path: []const u8) !void {
327}328}
328329
329/// Same as `deleteDir` except the parameter is a null-terminated UTF8-encoded string.330/// 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 {
331 return os.rmdirC(dir_path);332 return os.rmdirC(dir_path);
332}333}
333334
334/// Same as `deleteDir` except the parameter is a null-terminated UTF16LE-encoded string.335/// 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 {
336 return os.rmdirW(dir_path);337 return os.rmdirW(dir_path);
337}338}
338339
...@@ -533,7 +534,7 @@ pub const Dir = struct {...@@ -533,7 +534,7 @@ pub const Dir = struct {
533 const next_index = self.index + linux_entry.reclen();534 const next_index = self.index + linux_entry.reclen();
534 self.index = next_index;535 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
538 // skip . and .. entries539 // skip . and .. entries
539 if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {540 if (mem.eql(u8, name, ".") or mem.eql(u8, name, "..")) {
...@@ -688,7 +689,7 @@ pub const Dir = struct {...@@ -688,7 +689,7 @@ pub const Dir = struct {
688 }689 }
689690
690 /// Same as `open` except the parameter is null-terminated.691 /// 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 {
692 return cwd().openDirC(dir_path_c);693 return cwd().openDirC(dir_path_c);
693 }694 }
694695
...@@ -708,7 +709,7 @@ pub const Dir = struct {...@@ -708,7 +709,7 @@ pub const Dir = struct {
708 }709 }
709710
710 /// Call `File.close` on the result when done.711 /// 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 {
712 if (builtin.os == .windows) {713 if (builtin.os == .windows) {
713 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);714 const path_w = try os.windows.cStrToPrefixedFileW(sub_path);
714 return self.openReadW(&path_w);715 return self.openReadW(&path_w);
...@@ -719,7 +720,7 @@ pub const Dir = struct {...@@ -719,7 +720,7 @@ pub const Dir = struct {
719 return File.openHandle(fd);720 return File.openHandle(fd);
720 }721 }
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 {
723 const w = os.windows;724 const w = os.windows;
724725
725 var result = File{ .handle = undefined };726 var result = File{ .handle = undefined };
...@@ -786,7 +787,7 @@ pub const Dir = struct {...@@ -786,7 +787,7 @@ pub const Dir = struct {
786 }787 }
787788
788 /// Same as `openDir` except the parameter is null-terminated.789 /// 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 {
790 if (builtin.os == .windows) {791 if (builtin.os == .windows) {
791 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);792 const sub_path_w = try os.windows.cStrToPrefixedFileW(sub_path_c);
792 return self.openDirW(&sub_path_w);793 return self.openDirW(&sub_path_w);
...@@ -805,7 +806,7 @@ pub const Dir = struct {...@@ -805,7 +806,7 @@ pub const Dir = struct {
805806
806 /// Same as `openDir` except the path parameter is UTF16LE, NT-prefixed.807 /// Same as `openDir` except the path parameter is UTF16LE, NT-prefixed.
807 /// This function is Windows-only.808 /// 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 {
809 const w = os.windows;810 const w = os.windows;
810811
811 var result = Dir{812 var result = Dir{
...@@ -868,7 +869,7 @@ pub const Dir = struct {...@@ -868,7 +869,7 @@ pub const Dir = struct {
868 }869 }
869870
870 /// Same as `deleteFile` except the parameter is null-terminated.871 /// 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 {
872 os.unlinkatC(self.fd, sub_path_c, 0) catch |err| switch (err) {873 os.unlinkatC(self.fd, sub_path_c, 0) catch |err| switch (err) {
873 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR874 error.DirNotEmpty => unreachable, // not passing AT_REMOVEDIR
874 else => |e| return e,875 else => |e| return e,
...@@ -903,7 +904,7 @@ pub const Dir = struct {...@@ -903,7 +904,7 @@ pub const Dir = struct {
903 }904 }
904905
905 /// Same as `deleteDir` except the parameter is null-terminated.906 /// 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 {
907 os.unlinkatC(self.fd, sub_path_c, os.AT_REMOVEDIR) catch |err| switch (err) {908 os.unlinkatC(self.fd, sub_path_c, os.AT_REMOVEDIR) catch |err| switch (err) {
908 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR909 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
909 else => |e| return e,910 else => |e| return e,
...@@ -912,7 +913,7 @@ pub const Dir = struct {...@@ -912,7 +913,7 @@ pub const Dir = struct {
912913
913 /// Same as `deleteDir` except the parameter is UTF16LE, NT prefixed.914 /// Same as `deleteDir` except the parameter is UTF16LE, NT prefixed.
914 /// This function is Windows-only.915 /// 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 {
916 os.unlinkatW(self.fd, sub_path_w, os.AT_REMOVEDIR) catch |err| switch (err) {917 os.unlinkatW(self.fd, sub_path_w, os.AT_REMOVEDIR) catch |err| switch (err) {
917 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR918 error.IsDir => unreachable, // not possible since we pass AT_REMOVEDIR
918 else => |e| return e,919 else => |e| return e,
...@@ -927,7 +928,7 @@ pub const Dir = struct {...@@ -927,7 +928,7 @@ pub const Dir = struct {
927 }928 }
928929
929 /// Same as `readLink`, except the `pathname` parameter is null-terminated.930 /// 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 {
931 return os.readlinkatC(self.fd, sub_path_c, buffer);932 return os.readlinkatC(self.fd, sub_path_c, buffer);
932 }933 }
933934
...@@ -1240,7 +1241,7 @@ pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfE...@@ -1240,7 +1241,7 @@ pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfE
12401241
1241pub fn openSelfExe() OpenSelfExeError!File {1242pub fn openSelfExe() OpenSelfExeError!File {
1242 if (builtin.os == .linux) {1243 if (builtin.os == .linux) {
1243 return File.openReadC(c"/proc/self/exe");1244 return File.openReadC("/proc/self/exe");
1244 }1245 }
1245 if (builtin.os == .windows) {1246 if (builtin.os == .windows) {
1246 const wide_slice = selfExePathW();1247 const wide_slice = selfExePathW();
...@@ -1250,7 +1251,8 @@ pub fn openSelfExe() OpenSelfExeError!File {...@@ -1250,7 +1251,8 @@ pub fn openSelfExe() OpenSelfExeError!File {
1250 var buf: [MAX_PATH_BYTES]u8 = undefined;1251 var buf: [MAX_PATH_BYTES]u8 = undefined;
1251 const self_exe_path = try selfExePath(&buf);1252 const self_exe_path = try selfExePath(&buf);
1252 buf[self_exe_path.len] = 0;1253 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));
1254}1256}
12551257
1256test "openSelfExe" {1258test "openSelfExe" {
...@@ -1277,23 +1279,23 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {...@@ -1277,23 +1279,23 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
1277 var u32_len: u32 = out_buffer.len;1279 var u32_len: u32 = out_buffer.len;
1278 const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);1280 const rc = std.c._NSGetExecutablePath(out_buffer, &u32_len);
1279 if (rc != 0) return error.NameTooLong;1281 if (rc != 0) return error.NameTooLong;
1280 return mem.toSlice(u8, out_buffer);1282 return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer));
1281 }1283 }
1282 switch (builtin.os) {1284 switch (builtin.os) {
1283 .linux => return os.readlinkC(c"/proc/self/exe", out_buffer),1285 .linux => return os.readlinkC("/proc/self/exe", out_buffer),
1284 .freebsd, .dragonfly => {1286 .freebsd, .dragonfly => {
1285 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };1287 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
1286 var out_len: usize = out_buffer.len;1288 var out_len: usize = out_buffer.len;
1287 try os.sysctl(&mib, out_buffer, &out_len, null, 0);1289 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
1288 // TODO could this slice from 0 to out_len instead?1290 // 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));
1290 },1292 },
1291 .netbsd => {1293 .netbsd => {
1292 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };1294 var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC_ARGS, -1, os.KERN_PROC_PATHNAME };
1293 var out_len: usize = out_buffer.len;1295 var out_len: usize = out_buffer.len;
1294 try os.sysctl(&mib, out_buffer, &out_len, null, 0);1296 try os.sysctl(&mib, out_buffer, &out_len, null, 0);
1295 // TODO could this slice from 0 to out_len instead?1297 // 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));
1297 },1299 },
1298 .windows => {1300 .windows => {
1299 const utf16le_slice = selfExePathW();1301 const utf16le_slice = selfExePathW();
...@@ -1306,9 +1308,9 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {...@@ -1306,9 +1308,9 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
1306}1308}
13071309
1308/// The result is UTF16LE-encoded.1310/// The result is UTF16LE-encoded.
1309pub fn selfExePathW() []const u16 {1311pub fn selfExePathW() [:0]const u16 {
1310 const image_path_name = &os.windows.peb().ProcessParameters.ImagePathName;1312 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));
1312}1314}
13131315
1314/// `selfExeDirPath` except allocates the result on the heap.1316/// `selfExeDirPath` except allocates the result on the heap.
...@@ -1326,7 +1328,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const...@@ -1326,7 +1328,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const
1326 // the file path looks something like `/a/b/c/exe (deleted)`1328 // the file path looks something like `/a/b/c/exe (deleted)`
1327 // This path cannot be opened, but it's valid for determining the directory1329 // This path cannot be opened, but it's valid for determining the directory
1328 // the executable was in when it was run.1330 // 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);
1330 // Assume that /proc/self/exe has an absolute path, and therefore dirname1332 // Assume that /proc/self/exe has an absolute path, and therefore dirname
1331 // will not return null.1333 // will not return null.
1332 return path.dirname(full_exe_path).?;1334 return path.dirname(full_exe_path).?;
lib/std/fs/file.zig+8-8
...@@ -31,7 +31,7 @@ pub const File = struct {...@@ -31,7 +31,7 @@ pub const File = struct {
31 }31 }
3232
33 /// Deprecated; call `std.fs.Dir.openReadC` directly.33 /// 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 {
35 return std.fs.Dir.cwd().openReadC(path_c);35 return std.fs.Dir.cwd().openReadC(path_c);
36 }36 }
3737
...@@ -61,7 +61,7 @@ pub const File = struct {...@@ -61,7 +61,7 @@ pub const File = struct {
6161
62 /// Same as `openWriteMode` except `path` is null-terminated.62 /// Same as `openWriteMode` except `path` is null-terminated.
63 /// TODO: deprecate this and move it to `std.fs.Dir`.63 /// 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 {
65 if (builtin.os == .windows) {65 if (builtin.os == .windows) {
66 const path_w = try windows.cStrToPrefixedFileW(path);66 const path_w = try windows.cStrToPrefixedFileW(path);
67 return openWriteModeW(&path_w, file_mode);67 return openWriteModeW(&path_w, file_mode);
...@@ -74,7 +74,7 @@ pub const File = struct {...@@ -74,7 +74,7 @@ pub const File = struct {
7474
75 /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded75 /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded
76 /// TODO: deprecate this and move it to `std.fs.Dir`.76 /// 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 {
78 const handle = try windows.CreateFileW(78 const handle = try windows.CreateFileW(
79 path_w,79 path_w,
80 windows.GENERIC_WRITE,80 windows.GENERIC_WRITE,
...@@ -101,7 +101,7 @@ pub const File = struct {...@@ -101,7 +101,7 @@ pub const File = struct {
101 }101 }
102102
103 /// TODO: deprecate this and move it to `std.fs.Dir`.103 /// 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 {
105 if (builtin.os == .windows) {105 if (builtin.os == .windows) {
106 const path_w = try windows.cStrToPrefixedFileW(path);106 const path_w = try windows.cStrToPrefixedFileW(path);
107 return openWriteNoClobberW(&path_w, file_mode);107 return openWriteNoClobberW(&path_w, file_mode);
...@@ -113,7 +113,7 @@ pub const File = struct {...@@ -113,7 +113,7 @@ pub const File = struct {
113 }113 }
114114
115 /// TODO: deprecate this and move it to `std.fs.Dir`.115 /// 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 {
117 const handle = try windows.CreateFileW(117 const handle = try windows.CreateFileW(
118 path_w,118 path_w,
119 windows.GENERIC_WRITE,119 windows.GENERIC_WRITE,
...@@ -142,13 +142,13 @@ pub const File = struct {...@@ -142,13 +142,13 @@ pub const File = struct {
142142
143 /// Same as `access` except the parameter is null-terminated.143 /// Same as `access` except the parameter is null-terminated.
144 /// TODO: deprecate this and move it to `std.fs.Dir`.144 /// 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 {
146 return os.accessC(path, os.F_OK);146 return os.accessC(path, os.F_OK);
147 }147 }
148148
149 /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.149 /// Same as `access` except the parameter is null-terminated UTF16LE-encoded.
150 /// TODO: deprecate this and move it to `std.fs.Dir`.150 /// 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 {
152 return os.accessW(path, os.F_OK);152 return os.accessW(path, os.F_OK);
153 }153 }
154154
...@@ -172,7 +172,7 @@ pub const File = struct {...@@ -172,7 +172,7 @@ pub const File = struct {
172 if (self.isTty()) {172 if (self.isTty()) {
173 if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) {173 if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) {
174 // Use getenvC to workaround https://github.com/ziglang/zig/issues/3511174 // Use getenvC to workaround https://github.com/ziglang/zig/issues/3511
175 if (os.getenvC(c"TERM")) |term| {175 if (os.getenvC("TERM")) |term| {
176 if (std.mem.eql(u8, term, "dumb"))176 if (std.mem.eql(u8, term, "dumb"))
177 return false;177 return false;
178 }178 }
lib/std/fs/path.zig+1-1
...@@ -394,7 +394,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {...@@ -394,7 +394,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
394 }394 }
395395
396 // determine which disk designator we will result with, if any396 // determine which disk designator we will result with, if any
397 var result_drive_buf = "_:";397 var result_drive_buf = "_:".*;
398 var result_disk_designator: []const u8 = "";398 var result_disk_designator: []const u8 = "";
399 var have_drive_kind = WindowsPath.Kind.None;399 var have_drive_kind = WindowsPath.Kind.None;
400 var have_abs_path = false;400 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...@@ -202,70 +202,70 @@ const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x
202202
203test "siphash64-2-4 sanity" {203test "siphash64-2-4 sanity" {
204 const vectors = [_][8]u8{204 const vectors = [_][8]u8{
205 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""205 "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72".*, // ""
206 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"206 "\xfd\x67\xdc\x93\xc5\x39\xf8\x74".*, // "\x00"
207 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc207 "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d".*, // "\x00\x01" ... etc
208 "\x2d\x7e\xfb\xd7\x96\x66\x67\x85",208 "\x2d\x7e\xfb\xd7\x96\x66\x67\x85".*,
209 "\xb7\x87\x71\x27\xe0\x94\x27\xcf",209 "\xb7\x87\x71\x27\xe0\x94\x27\xcf".*,
210 "\x8d\xa6\x99\xcd\x64\x55\x76\x18",210 "\x8d\xa6\x99\xcd\x64\x55\x76\x18".*,
211 "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb",211 "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb".*,
212 "\x37\xd1\x01\x8b\xf5\x00\x02\xab",212 "\x37\xd1\x01\x8b\xf5\x00\x02\xab".*,
213 "\x62\x24\x93\x9a\x79\xf5\xf5\x93",213 "\x62\x24\x93\x9a\x79\xf5\xf5\x93".*,
214 "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e",214 "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e".*,
215 "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a",215 "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a".*,
216 "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4",216 "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4".*,
217 "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75",217 "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75".*,
218 "\x90\x3d\x84\xc0\x27\x56\xea\x14",218 "\x90\x3d\x84\xc0\x27\x56\xea\x14".*,
219 "\xee\xf2\x7a\x8e\x90\xca\x23\xf7",219 "\xee\xf2\x7a\x8e\x90\xca\x23\xf7".*,
220 "\xe5\x45\xbe\x49\x61\xca\x29\xa1",220 "\xe5\x45\xbe\x49\x61\xca\x29\xa1".*,
221 "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f",221 "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f".*,
222 "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69",222 "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69".*,
223 "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b",223 "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b".*,
224 "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb",224 "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb".*,
225 "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe",225 "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe".*,
226 "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0",226 "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0".*,
227 "\x88\x3e\xa3\xe3\x95\x67\x53\x93",227 "\x88\x3e\xa3\xe3\x95\x67\x53\x93".*,
228 "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8",228 "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8".*,
229 "\x94\xaf\x49\xf6\xc6\x50\xad\xb8",229 "\x94\xaf\x49\xf6\xc6\x50\xad\xb8".*,
230 "\xea\xb8\x85\x8a\xde\x92\xe1\xbc",230 "\xea\xb8\x85\x8a\xde\x92\xe1\xbc".*,
231 "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17",231 "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17".*,
232 "\xad\xcf\x6b\x07\x63\x61\x2e\x2f",232 "\xad\xcf\x6b\x07\x63\x61\x2e\x2f".*,
233 "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde",233 "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde".*,
234 "\x71\x65\x95\x87\x66\x50\xa2\xa6",234 "\x71\x65\x95\x87\x66\x50\xa2\xa6".*,
235 "\x28\xef\x49\x5c\x53\xa3\x87\xad",235 "\x28\xef\x49\x5c\x53\xa3\x87\xad".*,
236 "\x42\xc3\x41\xd8\xfa\x92\xd8\x32",236 "\x42\xc3\x41\xd8\xfa\x92\xd8\x32".*,
237 "\xce\x7c\xf2\x72\x2f\x51\x27\x71",237 "\xce\x7c\xf2\x72\x2f\x51\x27\x71".*,
238 "\xe3\x78\x59\xf9\x46\x23\xf3\xa7",238 "\xe3\x78\x59\xf9\x46\x23\xf3\xa7".*,
239 "\x38\x12\x05\xbb\x1a\xb0\xe0\x12",239 "\x38\x12\x05\xbb\x1a\xb0\xe0\x12".*,
240 "\xae\x97\xa1\x0f\xd4\x34\xe0\x15",240 "\xae\x97\xa1\x0f\xd4\x34\xe0\x15".*,
241 "\xb4\xa3\x15\x08\xbe\xff\x4d\x31",241 "\xb4\xa3\x15\x08\xbe\xff\x4d\x31".*,
242 "\x81\x39\x62\x29\xf0\x90\x79\x02",242 "\x81\x39\x62\x29\xf0\x90\x79\x02".*,
243 "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca",243 "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca".*,
244 "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a",244 "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a".*,
245 "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e",245 "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e".*,
246 "\x92\x59\x58\xfc\xd6\x42\x0c\xad",246 "\x92\x59\x58\xfc\xd6\x42\x0c\xad".*,
247 "\xa9\x15\xc2\x9b\xc8\x06\x73\x18",247 "\xa9\x15\xc2\x9b\xc8\x06\x73\x18".*,
248 "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4",248 "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4".*,
249 "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9",249 "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9".*,
250 "\x87\x57\x75\x19\x04\x8f\x53\xa9",250 "\x87\x57\x75\x19\x04\x8f\x53\xa9".*,
251 "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb",251 "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb".*,
252 "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0",252 "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0".*,
253 "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6",253 "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6".*,
254 "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7",254 "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7".*,
255 "\x72\xfe\x52\x97\x5a\x43\x64\xee",255 "\x72\xfe\x52\x97\x5a\x43\x64\xee".*,
256 "\x5a\x16\x45\xb2\x76\xd5\x92\xa1",256 "\x5a\x16\x45\xb2\x76\xd5\x92\xa1".*,
257 "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a",257 "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a".*,
258 "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81",258 "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81".*,
259 "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f",259 "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f".*,
260 "\x99\x24\xa4\x3c\xc1\x31\x57\x24",260 "\x99\x24\xa4\x3c\xc1\x31\x57\x24".*,
261 "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7",261 "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7".*,
262 "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea",262 "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea".*,
263 "\x13\x50\x79\xa3\x23\x1c\xe6\x60",263 "\x13\x50\x79\xa3\x23\x1c\xe6\x60".*,
264 "\x93\x2b\x28\x46\xe4\xd7\x06\x66",264 "\x93\x2b\x28\x46\xe4\xd7\x06\x66".*,
265 "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c",265 "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c".*,
266 "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f",266 "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f".*,
267 "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5",267 "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5".*,
268 "\x72\x45\x06\xeb\x4c\x32\x8a\x95",268 "\x72\x45\x06\xeb\x4c\x32\x8a\x95".*,
269 };269 };
270270
271 const siphash = SipHash64(2, 4);271 const siphash = SipHash64(2, 4);
...@@ -281,70 +281,70 @@ test "siphash64-2-4 sanity" {...@@ -281,70 +281,70 @@ test "siphash64-2-4 sanity" {
281281
282test "siphash128-2-4 sanity" {282test "siphash128-2-4 sanity" {
283 const vectors = [_][16]u8{283 const vectors = [_][16]u8{
284 "\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",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",347 "\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c".*,
348 };348 };
349349
350 const siphash = SipHash128(2, 4);350 const siphash = SipHash128(2, 4);
lib/std/io/test.zig+2-2
...@@ -595,8 +595,8 @@ test "Deserializer bad data" {...@@ -595,8 +595,8 @@ test "Deserializer bad data" {
595test "c out stream" {595test "c out stream" {
596 if (!builtin.link_libc) return error.SkipZigTest;596 if (!builtin.link_libc) return error.SkipZigTest;
597597
598 const filename = c"tmp_io_test_file.txt";598 const filename = "tmp_io_test_file.txt";
599 const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;599 const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
600 defer {600 defer {
601 _ = std.c.fclose(out_file);601 _ = std.c.fclose(out_file);
602 fs.deleteFileC(filename) catch {};602 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 {...@@ -356,17 +356,17 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
356 return true;356 return true;
357}357}
358358
359pub fn len(comptime T: type, ptr: [*]const T) usize {359pub fn len(comptime T: type, ptr: [*:0]const T) usize {
360 var count: usize = 0;360 var count: usize = 0;
361 while (ptr[count] != 0) : (count += 1) {}361 while (ptr[count] != 0) : (count += 1) {}
362 return count;362 return count;
363}363}
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 {
366 return ptr[0..len(T, ptr)];366 return ptr[0..len(T, ptr)];
367}367}
368368
369pub fn toSlice(comptime T: type, ptr: [*]T) []T {369pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T {
370 return ptr[0..len(T, ptr)];370 return ptr[0..len(T, ptr)];
371}371}
372372
...@@ -1408,7 +1408,9 @@ test "toBytes" {...@@ -1408,7 +1408,9 @@ test "toBytes" {
1408fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {1408fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
1409 const size = @as(usize, @sizeOf(T));1409 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 {
1412 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));1414 @compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));
1413 }1415 }
14141416
...@@ -1430,12 +1432,12 @@ test "bytesAsValue" {...@@ -1430,12 +1432,12 @@ test "bytesAsValue" {
1430 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",1432 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
1431 };1433 };
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) {
1436 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",1438 builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
1437 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",1439 builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
1438 };1440 }.*;
1439 var codeface = bytesAsValue(u32, &codeface_bytes);1441 var codeface = bytesAsValue(u32, &codeface_bytes);
1440 testing.expect(codeface.* == 0xC0DEFACE);1442 testing.expect(codeface.* == 0xC0DEFACE);
1441 codeface.* = 0;1443 codeface.* = 0;
...@@ -1456,14 +1458,14 @@ test "bytesAsValue" {...@@ -1456,14 +1458,14 @@ test "bytesAsValue" {
1456 .d = 0xA1,1458 .d = 0xA1,
1457 };1459 };
1458 const inst_bytes = "\xBE\xEF\xDE\xA1";1460 const inst_bytes = "\xBE\xEF\xDE\xA1";
1459 const inst2 = bytesAsValue(S, &inst_bytes);1461 const inst2 = bytesAsValue(S, inst_bytes);
1460 testing.expect(meta.eql(inst, inst2.*));1462 testing.expect(meta.eql(inst, inst2.*));
1461}1463}
14621464
1463///Given a pointer to an array of bytes, returns a value of the specified type backed by a1465///Given a pointer to an array of bytes, returns a value of the specified type backed by a
1464/// copy of those bytes.1466/// copy of those bytes.
1465pub fn bytesToValue(comptime T: type, bytes: var) T {1467pub fn bytesToValue(comptime T: type, bytes: var) T {
1466 return bytesAsValue(T, &bytes).*;1468 return bytesAsValue(T, bytes).*;
1467}1469}
1468test "bytesToValue" {1470test "bytesToValue" {
1469 const deadbeef_bytes = switch (builtin.endian) {1471 const deadbeef_bytes = switch (builtin.endian) {
...@@ -1491,11 +1493,11 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA...@@ -1491,11 +1493,11 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
1491}1493}
14921494
1493test "subArrayPtr" {1495test "subArrayPtr" {
1494 const a1 = "abcdef";1496 const a1: [6]u8 = "abcdef".*;
1495 const sub1 = subArrayPtr(&a1, 2, 3);1497 const sub1 = subArrayPtr(&a1, 2, 3);
1496 testing.expect(eql(u8, sub1.*, "cde"));1498 testing.expect(eql(u8, sub1.*, "cde"));
14971499
1498 var a2 = "abcdef";1500 var a2: [6]u8 = "abcdef".*;
1499 var sub2 = subArrayPtr(&a2, 2, 3);1501 var sub2 = subArrayPtr(&a2, 2, 3);
15001502
1501 testing.expect(eql(u8, sub2, "cde"));1503 testing.expect(eql(u8, sub2, "cde"));
lib/std/meta.zig+6-6
...@@ -469,19 +469,19 @@ test "std.meta.eql" {...@@ -469,19 +469,19 @@ test "std.meta.eql" {
469 const s_1 = S{469 const s_1 = S{
470 .a = 134,470 .a = 134,
471 .b = 123.3,471 .b = 123.3,
472 .c = "12345",472 .c = "12345".*,
473 };473 };
474474
475 const s_2 = S{475 const s_2 = S{
476 .a = 1,476 .a = 1,
477 .b = 123.3,477 .b = 123.3,
478 .c = "54321",478 .c = "54321".*,
479 };479 };
480480
481 const s_3 = S{481 const s_3 = S{
482 .a = 134,482 .a = 134,
483 .b = 123.3,483 .b = 123.3,
484 .c = "12345",484 .c = "12345".*,
485 };485 };
486486
487 const u_1 = U{ .f = 24 };487 const u_1 = U{ .f = 24 };
...@@ -494,9 +494,9 @@ test "std.meta.eql" {...@@ -494,9 +494,9 @@ test "std.meta.eql" {
494 testing.expect(eql(u_1, u_3));494 testing.expect(eql(u_1, u_3));
495 testing.expect(!eql(u_1, u_2));495 testing.expect(!eql(u_1, u_2));
496496
497 var a1 = "abcdef";497 var a1 = "abcdef".*;
498 var a2 = "abcdef";498 var a2 = "abcdef".*;
499 var a3 = "ghijkl";499 var a3 = "ghijkl".*;
500500
501 testing.expect(eql(a1, a2));501 testing.expect(eql(a1, a2));
502 testing.expect(!eql(a1, a3));502 testing.expect(!eql(a1, a3));
lib/std/meta/trait.zig-2
...@@ -319,7 +319,6 @@ test "std.meta.trait.isNumber" {...@@ -319,7 +319,6 @@ test "std.meta.trait.isNumber" {
319 testing.expect(!isNumber(NotANumber));319 testing.expect(!isNumber(NotANumber));
320}320}
321321
322///
323pub fn isConstPtr(comptime T: type) bool {322pub fn isConstPtr(comptime T: type) bool {
324 if (!comptime is(builtin.TypeId.Pointer)(T)) return false;323 if (!comptime is(builtin.TypeId.Pointer)(T)) return false;
325 const info = @typeInfo(T);324 const info = @typeInfo(T);
...@@ -335,7 +334,6 @@ test "std.meta.trait.isConstPtr" {...@@ -335,7 +334,6 @@ test "std.meta.trait.isConstPtr" {
335 testing.expect(!isConstPtr(@typeOf(6)));334 testing.expect(!isConstPtr(@typeOf(6)));
336}335}
337336
338///
339pub fn isContainer(comptime T: type) bool {337pub fn isContainer(comptime T: type) bool {
340 const info = @typeInfo(T);338 const info = @typeInfo(T);
341 return switch (info) {339 return switch (info) {
lib/std/net.zig+10-10
...@@ -360,7 +360,7 @@ pub const Address = extern union {...@@ -360,7 +360,7 @@ pub const Address = extern union {
360 unreachable;360 unreachable;
361 }361 }
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));
364 return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len);364 return @intCast(os.socklen_t, @sizeOf(os.sockaddr_un) - self.un.path.len + path_len);
365 },365 },
366 else => unreachable,366 else => unreachable,
...@@ -666,35 +666,35 @@ const Policy = struct {...@@ -666,35 +666,35 @@ const Policy = struct {
666666
667const defined_policies = [_]Policy{667const defined_policies = [_]Policy{
668 Policy{668 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".*,
670 .len = 15,670 .len = 15,
671 .mask = 0xff,671 .mask = 0xff,
672 .prec = 50,672 .prec = 50,
673 .label = 0,673 .label = 0,
674 },674 },
675 Policy{675 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".*,
677 .len = 11,677 .len = 11,
678 .mask = 0xff,678 .mask = 0xff,
679 .prec = 35,679 .prec = 35,
680 .label = 4,680 .label = 4,
681 },681 },
682 Policy{682 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".*,
684 .len = 1,684 .len = 1,
685 .mask = 0xff,685 .mask = 0xff,
686 .prec = 30,686 .prec = 30,
687 .label = 2,687 .label = 2,
688 },688 },
689 Policy{689 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".*,
691 .len = 3,691 .len = 3,
692 .mask = 0xff,692 .mask = 0xff,
693 .prec = 5,693 .prec = 5,
694 .label = 5,694 .label = 5,
695 },695 },
696 Policy{696 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".*,
698 .len = 0,698 .len = 0,
699 .mask = 0xfe,699 .mask = 0xfe,
700 .prec = 3,700 .prec = 3,
...@@ -708,7 +708,7 @@ const defined_policies = [_]Policy{...@@ -708,7 +708,7 @@ const defined_policies = [_]Policy{
708 // { "\x3f\xfe", 1, 0xff, 1, 12 },708 // { "\x3f\xfe", 1, 0xff, 1, 12 },
709 // Last rule must match all addresses to stop loop.709 // Last rule must match all addresses to stop loop.
710 Policy{710 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".*,
712 .len = 0,712 .len = 0,
713 .mask = 0,713 .mask = 0,
714 .prec = 40,714 .prec = 40,
...@@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(...@@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(
812 family: os.sa_family_t,812 family: os.sa_family_t,
813 port: u16,813 port: u16,
814) !void {814) !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) {
816 error.FileNotFound,816 error.FileNotFound,
817 error.NotDir,817 error.NotDir,
818 error.AccessDenied,818 error.AccessDenied,
...@@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {...@@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
1006 };1006 };
1007 errdefer rc.deinit();1007 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) {
1010 error.FileNotFound,1010 error.FileNotFound,
1011 error.NotDir,1011 error.NotDir,
1012 error.AccessDenied,1012 error.AccessDenied,
...@@ -1271,7 +1271,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)...@@ -1271,7 +1271,7 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8)
1271 var tmp: [256]u8 = undefined;1271 var tmp: [256]u8 = undefined;
1272 // Returns len of compressed name. strlen to get canon name.1272 // Returns len of compressed name. strlen to get canon name.
1273 _ = try os.dn_expand(packet, data, &tmp);1273 _ = 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));
1275 if (isValidHostName(canon_name)) {1275 if (isValidHostName(canon_name)) {
1276 try ctx.canon.replaceContents(canon_name);1276 try ctx.canon.replaceContents(canon_name);
1277 }1277 }
lib/std/os.zig+52-47
...@@ -66,12 +66,12 @@ pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {...@@ -66,12 +66,12 @@ pub const system = if (builtin.link_libc) std.c else switch (builtin.os) {
66pub usingnamespace @import("os/bits.zig");66pub usingnamespace @import("os/bits.zig");
6767
68/// See also `getenv`. Populated by startup code before main().68/// See also `getenv`. Populated by startup code before main().
69pub var environ: [][*]u8 = undefined;69pub var environ: [][*:0]u8 = undefined;
7070
71/// Populated by startup code before main().71/// Populated by startup code before main().
72/// Not available on Windows. See `std.process.args`72/// Not available on Windows. See `std.process.args`
73/// for obtaining the process arguments.73/// for obtaining the process arguments.
74pub var argv: [][*]u8 = undefined;74pub var argv: [][*:0]u8 = undefined;
7575
76/// To obtain errno, call this function with the return value of the76/// To obtain errno, call this function with the return value of the
77/// system function call. For some systems this will obtain the value directly77/// system function call. For some systems this will obtain the value directly
...@@ -157,7 +157,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {...@@ -157,7 +157,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
157}157}
158158
159fn getRandomBytesDevURandom(buf: []u8) !void {159fn 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);
161 defer close(fd);161 defer close(fd);
162162
163 const st = try fstat(fd);163 const st = try fstat(fd);
...@@ -655,8 +655,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {...@@ -655,8 +655,7 @@ pub fn open(file_path: []const u8, flags: u32, perm: usize) OpenError!fd_t {
655655
656/// Open and possibly create a file. Keeps trying if it gets interrupted.656/// Open and possibly create a file. Keeps trying if it gets interrupted.
657/// See also `open`.657/// See also `open`.
658/// TODO https://github.com/ziglang/zig/issues/265658pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t {
659pub fn openC(file_path: [*]const u8, flags: u32, perm: usize) OpenError!fd_t {
660 while (true) {659 while (true) {
661 const rc = system.open(file_path, flags, perm);660 const rc = system.open(file_path, flags, perm);
662 switch (errno(rc)) {661 switch (errno(rc)) {
...@@ -697,7 +696,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: usize) Open...@@ -697,7 +696,7 @@ pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: usize) Open
697/// Open and possibly create a file. Keeps trying if it gets interrupted.696/// Open and possibly create a file. Keeps trying if it gets interrupted.
698/// `file_path` is relative to the open directory handle `dir_fd`.697/// `file_path` is relative to the open directory handle `dir_fd`.
699/// See also `openat`.698/// 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 {
701 while (true) {700 while (true) {
702 const rc = system.openat(dir_fd, file_path, flags, mode);701 const rc = system.openat(dir_fd, file_path, flags, mode);
703 switch (errno(rc)) {702 switch (errno(rc)) {
...@@ -757,7 +756,7 @@ pub const ExecveError = error{...@@ -757,7 +756,7 @@ pub const ExecveError = error{
757/// Like `execve` except the parameters are null-terminated,756/// Like `execve` except the parameters are null-terminated,
758/// matching the syscall API on all targets. This removes the need for an allocator.757/// matching the syscall API on all targets. This removes the need for an allocator.
759/// This function ignores PATH environment variable. See `execvpeC` for that.758/// 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 {
761 switch (errno(system.execve(path, child_argv, envp))) {760 switch (errno(system.execve(path, child_argv, envp))) {
762 0 => unreachable,761 0 => unreachable,
763 EFAULT => unreachable,762 EFAULT => unreachable,
...@@ -784,7 +783,7 @@ pub fn execveC(path: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]co...@@ -784,7 +783,7 @@ pub fn execveC(path: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]co
784/// matching the syscall API on all targets. This removes the need for an allocator.783/// matching the syscall API on all targets. This removes the need for an allocator.
785/// This function also uses the PATH environment variable to get the full path to the executable.784/// This function also uses the PATH environment variable to get the full path to the executable.
786/// If `file` is an absolute path, this is the same as `execveC`.785/// 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 {
788 const file_slice = mem.toSliceConst(u8, file);787 const file_slice = mem.toSliceConst(u8, file);
789 if (mem.indexOfScalar(u8, file_slice, '/') != null) return execveC(file, child_argv, envp);788 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...@@ -799,7 +798,8 @@ pub fn execvpeC(file: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]c
799 path_buf[search_path.len] = '/';798 path_buf[search_path.len] = '/';
800 mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice);799 mem.copy(u8, path_buf[search_path.len + 1 ..], file_slice);
801 path_buf[search_path.len + file_slice.len + 1] = 0;800 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);
803 switch (err) {803 switch (err) {
804 error.AccessDenied => seen_eacces = true,804 error.AccessDenied => seen_eacces = true,
805 error.FileNotFound, error.NotDir => {},805 error.FileNotFound, error.NotDir => {},
...@@ -820,8 +820,8 @@ pub fn execvpe(...@@ -820,8 +820,8 @@ pub fn execvpe(
820 argv_slice: []const []const u8,820 argv_slice: []const []const u8,
821 env_map: *const std.BufMap,821 env_map: *const std.BufMap,
822) (ExecveError || error{OutOfMemory}) {822) (ExecveError || error{OutOfMemory}) {
823 const argv_buf = try allocator.alloc(?[*]u8, argv_slice.len + 1);823 const argv_buf = try allocator.alloc(?[*:0]u8, argv_slice.len + 1);
824 mem.set(?[*]u8, argv_buf, null);824 mem.set(?[*:0]u8, argv_buf, null);
825 defer {825 defer {
826 for (argv_buf) |arg| {826 for (argv_buf) |arg| {
827 const arg_buf = if (arg) |ptr| mem.toSlice(u8, ptr) else break;827 const arg_buf = if (arg) |ptr| mem.toSlice(u8, ptr) else break;
...@@ -834,20 +834,24 @@ pub fn execvpe(...@@ -834,20 +834,24 @@ pub fn execvpe(
834 @memcpy(arg_buf.ptr, arg.ptr, arg.len);834 @memcpy(arg_buf.ptr, arg.ptr, arg.len);
835 arg_buf[arg.len] = 0;835 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);
838 }839 }
839 argv_buf[argv_slice.len] = null;840 argv_buf[argv_slice.len] = null;
840841
841 const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);842 const envp_buf = try createNullDelimitedEnvMap(allocator, env_map);
842 defer freeNullDelimitedEnvMap(allocator, envp_buf);843 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);
845}849}
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 {
848 const envp_count = env_map.count();852 const envp_count = env_map.count();
849 const envp_buf = try allocator.alloc(?[*]u8, envp_count + 1);853 const envp_buf = try allocator.alloc(?[*:0]u8, envp_count + 1);
850 mem.set(?[*]u8, envp_buf, null);854 mem.set(?[*:0]u8, envp_buf, null);
851 errdefer freeNullDelimitedEnvMap(allocator, envp_buf);855 errdefer freeNullDelimitedEnvMap(allocator, envp_buf);
852 {856 {
853 var it = env_map.iterator();857 var it = env_map.iterator();
...@@ -859,15 +863,17 @@ pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std....@@ -859,15 +863,17 @@ pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.
859 @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);863 @memcpy(env_buf.ptr + pair.key.len + 1, pair.value.ptr, pair.value.len);
860 env_buf[env_buf.len - 1] = 0;864 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);
863 }868 }
864 assert(i == envp_count);869 assert(i == envp_count);
865 }870 }
871 // TODO avoid @ptrCast here using slice syntax with https://github.com/ziglang/zig/issues/3731
866 assert(envp_buf[envp_count] == null);872 assert(envp_buf[envp_count] == null);
867 return envp_buf;873 return @ptrCast([*:null]?[*:0]u8, envp_buf.ptr)[0..envp_count];
868}874}
869875
870pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*]u8) void {876pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*:0]u8) void {
871 for (envp_buf) |env| {877 for (envp_buf) |env| {
872 const env_buf = if (env) |ptr| ptr[0 .. mem.len(u8, ptr) + 1] else break;878 const env_buf = if (env) |ptr| ptr[0 .. mem.len(u8, ptr) + 1] else break;
873 allocator.free(env_buf);879 allocator.free(env_buf);
...@@ -896,8 +902,7 @@ pub fn getenv(key: []const u8) ?[]const u8 {...@@ -896,8 +902,7 @@ pub fn getenv(key: []const u8) ?[]const u8 {
896902
897/// Get an environment variable with a null-terminated name.903/// Get an environment variable with a null-terminated name.
898/// See also `getenv`.904/// See also `getenv`.
899/// TODO https://github.com/ziglang/zig/issues/265905pub fn getenvC(key: [*:0]const u8) ?[]const u8 {
900pub fn getenvC(key: [*]const u8) ?[]const u8 {
901 if (builtin.link_libc) {906 if (builtin.link_libc) {
902 const value = system.getenv(key) orelse return null;907 const value = system.getenv(key) orelse return null;
903 return mem.toSliceConst(u8, value);908 return mem.toSliceConst(u8, value);
...@@ -922,7 +927,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {...@@ -922,7 +927,7 @@ pub fn getcwd(out_buffer: []u8) GetCwdError![]u8 {
922 break :blk errno(system.getcwd(out_buffer.ptr, out_buffer.len));927 break :blk errno(system.getcwd(out_buffer.ptr, out_buffer.len));
923 };928 };
924 switch (err) {929 switch (err) {
925 0 => return mem.toSlice(u8, out_buffer.ptr),930 0 => return mem.toSlice(u8, @ptrCast([*:0]u8, out_buffer.ptr)),
926 EFAULT => unreachable,931 EFAULT => unreachable,
927 EINVAL => unreachable,932 EINVAL => unreachable,
928 ENOENT => return error.CurrentWorkingDirectoryUnlinked,933 ENOENT => return error.CurrentWorkingDirectoryUnlinked,
...@@ -966,7 +971,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!...@@ -966,7 +971,7 @@ pub fn symlink(target_path: []const u8, sym_link_path: []const u8) SymLinkError!
966971
967/// This is the same as `symlink` except the parameters are null-terminated pointers.972/// This is the same as `symlink` except the parameters are null-terminated pointers.
968/// See also `symlink`.973/// 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 {
970 if (builtin.os == .windows) {975 if (builtin.os == .windows) {
971 const target_path_w = try windows.cStrToPrefixedFileW(target_path);976 const target_path_w = try windows.cStrToPrefixedFileW(target_path);
972 const sym_link_path_w = try windows.cStrToPrefixedFileW(sym_link_path);977 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...@@ -998,7 +1003,7 @@ pub fn symlinkat(target_path: []const u8, newdirfd: fd_t, sym_link_path: []const
998 return symlinkatC(target_path_c, newdirfd, sym_link_path_c);1003 return symlinkatC(target_path_c, newdirfd, sym_link_path_c);
999}1004}
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 {
1002 switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) {1007 switch (errno(system.symlinkat(target_path, newdirfd, sym_link_path))) {
1003 0 => return,1008 0 => return,
1004 EFAULT => unreachable,1009 EFAULT => unreachable,
...@@ -1052,7 +1057,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {...@@ -1052,7 +1057,7 @@ pub fn unlink(file_path: []const u8) UnlinkError!void {
1052}1057}
10531058
1054/// Same as `unlink` except the parameter is a null terminated UTF8-encoded string.1059/// 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 {
1056 if (builtin.os == .windows) {1061 if (builtin.os == .windows) {
1057 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1062 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1058 return windows.DeleteFileW(&file_path_w);1063 return windows.DeleteFileW(&file_path_w);
...@@ -1092,7 +1097,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo...@@ -1092,7 +1097,7 @@ pub fn unlinkat(dirfd: fd_t, file_path: []const u8, flags: u32) UnlinkatError!vo
1092}1097}
10931098
1094/// Same as `unlinkat` but `file_path` is a null-terminated string.1099/// 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 {
1096 if (builtin.os == .windows) {1101 if (builtin.os == .windows) {
1097 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);1102 const file_path_w = try windows.cStrToPrefixedFileW(file_path_c);
1098 return unlinkatW(dirfd, &file_path_w, flags);1103 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...@@ -1121,7 +1126,7 @@ pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatErro
1121}1126}
11221127
1123/// Same as `unlinkat` but `sub_path_w` is UTF16LE, NT prefixed. Windows only.1128/// 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 {
1125 const w = windows;1130 const w = windows;
11261131
1127 const want_rmdir_behavior = (flags & AT_REMOVEDIR) != 0;1132 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 {...@@ -1216,7 +1221,7 @@ pub fn rename(old_path: []const u8, new_path: []const u8) RenameError!void {
1216}1221}
12171222
1218/// Same as `rename` except the parameters are null-terminated byte arrays.1223/// 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 {
1220 if (builtin.os == .windows) {1225 if (builtin.os == .windows) {
1221 const old_path_w = try windows.cStrToPrefixedFileW(old_path);1226 const old_path_w = try windows.cStrToPrefixedFileW(old_path);
1222 const new_path_w = try windows.cStrToPrefixedFileW(new_path);1227 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 {...@@ -1248,7 +1253,7 @@ pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void {
12481253
1249/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.1254/// Same as `rename` except the parameters are null-terminated UTF16LE encoded byte arrays.
1250/// Assumes target is Windows.1255/// 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 {
1252 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;1257 const flags = windows.MOVEFILE_REPLACE_EXISTING | windows.MOVEFILE_WRITE_THROUGH;
1253 return windows.MoveFileExW(old_path, new_path, flags);1258 return windows.MoveFileExW(old_path, new_path, flags);
1254}1259}
...@@ -1282,7 +1287,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {...@@ -1282,7 +1287,7 @@ pub fn mkdir(dir_path: []const u8, mode: u32) MakeDirError!void {
1282}1287}
12831288
1284/// Same as `mkdir` but the parameter is a null-terminated UTF8-encoded string.1289/// 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 {
1286 if (builtin.os == .windows) {1291 if (builtin.os == .windows) {
1287 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1292 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1288 return windows.CreateDirectoryW(&dir_path_w, null);1293 return windows.CreateDirectoryW(&dir_path_w, null);
...@@ -1332,7 +1337,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {...@@ -1332,7 +1337,7 @@ pub fn rmdir(dir_path: []const u8) DeleteDirError!void {
1332}1337}
13331338
1334/// Same as `rmdir` except the parameter is null-terminated.1339/// 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 {
1336 if (builtin.os == .windows) {1341 if (builtin.os == .windows) {
1337 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1342 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1338 return windows.RemoveDirectoryW(&dir_path_w);1343 return windows.RemoveDirectoryW(&dir_path_w);
...@@ -1379,7 +1384,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {...@@ -1379,7 +1384,7 @@ pub fn chdir(dir_path: []const u8) ChangeCurDirError!void {
1379}1384}
13801385
1381/// Same as `chdir` except the parameter is null-terminated.1386/// 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 {
1383 if (builtin.os == .windows) {1388 if (builtin.os == .windows) {
1384 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);1389 const dir_path_w = try windows.cStrToPrefixedFileW(dir_path);
1385 @compileError("TODO implement chdir for Windows");1390 @compileError("TODO implement chdir for Windows");
...@@ -1421,7 +1426,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {...@@ -1421,7 +1426,7 @@ pub fn readlink(file_path: []const u8, out_buffer: []u8) ReadLinkError![]u8 {
1421}1426}
14221427
1423/// Same as `readlink` except `file_path` is null-terminated.1428/// 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 {
1425 if (builtin.os == .windows) {1430 if (builtin.os == .windows) {
1426 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1431 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1427 @compileError("TODO implement readlink for Windows");1432 @compileError("TODO implement readlink for Windows");
...@@ -1442,7 +1447,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {...@@ -1442,7 +1447,7 @@ pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 {
1442 }1447 }
1443}1448}
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 {
1446 if (builtin.os == .windows) {1451 if (builtin.os == .windows) {
1447 const file_path_w = try windows.cStrToPrefixedFileW(file_path);1452 const file_path_w = try windows.cStrToPrefixedFileW(file_path);
1448 @compileError("TODO implement readlink for Windows");1453 @compileError("TODO implement readlink for Windows");
...@@ -2129,7 +2134,7 @@ pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INoti...@@ -2129,7 +2134,7 @@ pub fn inotify_add_watch(inotify_fd: i32, pathname: []const u8, mask: u32) INoti
2129}2134}
21302135
2131/// Same as `inotify_add_watch` except pathname is null-terminated.2136/// 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 {
2133 const rc = system.inotify_add_watch(inotify_fd, pathname, mask);2138 const rc = system.inotify_add_watch(inotify_fd, pathname, mask);
2134 switch (errno(rc)) {2139 switch (errno(rc)) {
2135 0 => return @intCast(i32, rc),2140 0 => return @intCast(i32, rc),
...@@ -2286,7 +2291,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {...@@ -2286,7 +2291,7 @@ pub fn access(path: []const u8, mode: u32) AccessError!void {
2286}2291}
22872292
2288/// Same as `access` except `path` is null-terminated.2293/// 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 {
2290 if (builtin.os == .windows) {2295 if (builtin.os == .windows) {
2291 const path_w = try windows.cStrToPrefixedFileW(path);2296 const path_w = try windows.cStrToPrefixedFileW(path);
2292 _ = try windows.GetFileAttributesW(&path_w);2297 _ = try windows.GetFileAttributesW(&path_w);
...@@ -2313,7 +2318,7 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {...@@ -2313,7 +2318,7 @@ pub fn accessC(path: [*]const u8, mode: u32) AccessError!void {
2313/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.2318/// Call from Windows-specific code if you already have a UTF-16LE encoded, null terminated string.
2314/// Otherwise use `access` or `accessC`.2319/// Otherwise use `access` or `accessC`.
2315/// TODO currently this ignores `mode`.2320/// 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 {
2317 const ret = try windows.GetFileAttributesW(path);2322 const ret = try windows.GetFileAttributesW(path);
2318 if (ret != windows.INVALID_FILE_ATTRIBUTES) {2323 if (ret != windows.INVALID_FILE_ATTRIBUTES) {
2319 return;2324 return;
...@@ -2380,7 +2385,7 @@ pub fn sysctl(...@@ -2380,7 +2385,7 @@ pub fn sysctl(
2380}2385}
23812386
2382pub fn sysctlbynameC(2387pub fn sysctlbynameC(
2383 name: [*]const u8,2388 name: [*:0]const u8,
2384 oldp: ?*c_void,2389 oldp: ?*c_void,
2385 oldlenp: ?*usize,2390 oldlenp: ?*usize,
2386 newp: ?*c_void,2391 newp: ?*c_void,
...@@ -2562,7 +2567,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE...@@ -2562,7 +2567,7 @@ pub fn realpath(pathname: []const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathE
2562}2567}
25632568
2564/// Same as `realpath` except `pathname` is null-terminated.2569/// 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 {
2566 if (builtin.os == .windows) {2571 if (builtin.os == .windows) {
2567 const pathname_w = try windows.cStrToPrefixedFileW(pathname);2572 const pathname_w = try windows.cStrToPrefixedFileW(pathname);
2568 return realpathW(&pathname_w, out_buffer);2573 return realpathW(&pathname_w, out_buffer);
...@@ -2571,10 +2576,10 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat...@@ -2571,10 +2576,10 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
2571 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);2576 const fd = try openC(pathname, linux.O_PATH | linux.O_NONBLOCK | linux.O_CLOEXEC, 0);
2572 defer close(fd);2577 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;
2575 const proc_path = std.fmt.bufPrint(procfs_buf[0..], "/proc/self/fd/{}\x00", fd) catch unreachable;2580 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);
2578 }2583 }
2579 const result_path = std.c.realpath(pathname, out_buffer) orelse switch (std.c._errno().*) {2584 const result_path = std.c.realpath(pathname, out_buffer) orelse switch (std.c._errno().*) {
2580 EINVAL => unreachable,2585 EINVAL => unreachable,
...@@ -2593,7 +2598,7 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat...@@ -2593,7 +2598,7 @@ pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPat
2593}2598}
25942599
2595/// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded.2600/// 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 {
2597 const h_file = try windows.CreateFileW(2602 const h_file = try windows.CreateFileW(
2598 pathname,2603 pathname,
2599 windows.GENERIC_READ,2604 windows.GENERIC_READ,
...@@ -2674,7 +2679,7 @@ pub fn dl_iterate_phdr(...@@ -2674,7 +2679,7 @@ pub fn dl_iterate_phdr(
2674 if (it.end()) {2679 if (it.end()) {
2675 var info = dl_phdr_info{2680 var info = dl_phdr_info{
2676 .dlpi_addr = elf_base,2681 .dlpi_addr = elf_base,
2677 .dlpi_name = c"/proc/self/exe",2682 .dlpi_name = "/proc/self/exe",
2678 .dlpi_phdr = phdrs.ptr,2683 .dlpi_phdr = phdrs.ptr,
2679 .dlpi_phnum = ehdr.e_phnum,2684 .dlpi_phnum = ehdr.e_phnum,
2680 };2685 };
...@@ -2748,8 +2753,8 @@ pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {...@@ -2748,8 +2753,8 @@ pub fn sched_getaffinity(pid: pid_t) SchedGetAffinityError!cpu_set_t {
27482753
2749/// Used to convert a slice to a null terminated slice on the stack.2754/// Used to convert a slice to a null terminated slice on the stack.
2750/// TODO https://github.com/ziglang/zig/issues/2872755/// TODO https://github.com/ziglang/zig/issues/287
2751pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 {2756pub fn toPosixPath(file_path: []const u8) ![PATH_MAX-1:0]u8 {
2752 var path_with_null: [PATH_MAX]u8 = undefined;2757 var path_with_null: [PATH_MAX-1:0]u8 = undefined;
2753 // >= rather than > to make room for the null byte2758 // >= rather than > to make room for the null byte
2754 if (file_path.len >= PATH_MAX) return error.NameTooLong;2759 if (file_path.len >= PATH_MAX) return error.NameTooLong;
2755 mem.copy(u8, &path_with_null, file_path);2760 mem.copy(u8, &path_with_null, file_path);
...@@ -2854,7 +2859,7 @@ pub const GetHostNameError = error{PermissionDenied} || UnexpectedError;...@@ -2854,7 +2859,7 @@ pub const GetHostNameError = error{PermissionDenied} || UnexpectedError;
2854pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {2859pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
2855 if (builtin.link_libc) {2860 if (builtin.link_libc) {
2856 switch (errno(system.gethostname(name_buffer, name_buffer.len))) {2861 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)),
2858 EFAULT => unreachable,2863 EFAULT => unreachable,
2859 ENAMETOOLONG => unreachable, // HOST_NAME_MAX prevents this2864 ENAMETOOLONG => unreachable, // HOST_NAME_MAX prevents this
2860 EPERM => return error.PermissionDenied,2865 EPERM => return error.PermissionDenied,
...@@ -2865,7 +2870,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {...@@ -2865,7 +2870,7 @@ pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 {
2865 var uts: utsname = undefined;2870 var uts: utsname = undefined;
2866 switch (errno(system.uname(&uts))) {2871 switch (errno(system.uname(&uts))) {
2867 0 => {2872 0 => {
2868 const hostname = mem.toSlice(u8, &uts.nodename);2873 const hostname = mem.toSlice(u8, @ptrCast([*:0]u8, &uts.nodename));
2869 mem.copy(u8, name_buffer, hostname);2874 mem.copy(u8, name_buffer, hostname);
2870 return name_buffer[0..hostname.len];2875 return name_buffer[0..hostname.len];
2871 },2876 },
lib/std/os/bits/darwin.zig+1-1
...@@ -1205,7 +1205,7 @@ pub const addrinfo = extern struct {...@@ -1205,7 +1205,7 @@ pub const addrinfo = extern struct {
1205 socktype: i32,1205 socktype: i32,
1206 protocol: i32,1206 protocol: i32,
1207 addrlen: socklen_t,1207 addrlen: socklen_t,
1208 canonname: ?[*]u8,1208 canonname: ?[*:0]u8,
1209 addr: ?*sockaddr,1209 addr: ?*sockaddr,
1210 next: ?*addrinfo,1210 next: ?*addrinfo,
1211};1211};
lib/std/os/bits/linux.zig+1-1
...@@ -1363,7 +1363,7 @@ pub const addrinfo = extern struct {...@@ -1363,7 +1363,7 @@ pub const addrinfo = extern struct {
1363 protocol: i32,1363 protocol: i32,
1364 addrlen: socklen_t,1364 addrlen: socklen_t,
1365 addr: ?*sockaddr,1365 addr: ?*sockaddr,
1366 canonname: ?[*]u8,1366 canonname: ?[*:0]u8,
1367 next: ?*addrinfo,1367 next: ?*addrinfo,
1368};1368};
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...@@ -1053,7 +1053,7 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf
1053 if (it.end()) {1053 if (it.end()) {
1054 var info = dl_phdr_info{1054 var info = dl_phdr_info{
1055 .dlpi_addr = elf_base,1055 .dlpi_addr = elf_base,
1056 .dlpi_name = c"/proc/self/exe",1056 .dlpi_name = "/proc/self/exe",
1057 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),1057 .dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
1058 .dlpi_phnum = __ehdr_start.e_phnum,1058 .dlpi_phnum = __ehdr_start.e_phnum,
1059 };1059 };
lib/std/os/linux/test.zig+2-2
...@@ -56,7 +56,7 @@ test "statx" {...@@ -56,7 +56,7 @@ test "statx" {
56 }56 }
5757
58 var statx_buf: linux.Statx = undefined;58 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))) {
60 0 => {},60 0 => {},
61 // The statx syscall was only introduced in linux 4.1161 // The statx syscall was only introduced in linux 4.11
62 linux.ENOSYS => return error.SkipZigTest,62 linux.ENOSYS => return error.SkipZigTest,
...@@ -64,7 +64,7 @@ test "statx" {...@@ -64,7 +64,7 @@ test "statx" {
64 }64 }
6565
66 var stat_buf: linux.Stat = undefined;66 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))) {
68 0 => {},68 0 => {},
69 else => unreachable,69 else => unreachable,
70 }70 }
lib/std/os/linux/vdso.zig+4-2
...@@ -65,7 +65,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {...@@ -65,7 +65,8 @@ pub fn lookup(vername: []const u8, name: []const u8) usize {
65 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue;65 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info & 0xf) & OK_TYPES)) continue;
66 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue;66 if (0 == (@as(u32, 1) << @intCast(u5, syms[i].st_info >> 4) & OK_BINDS)) continue;
67 if (0 == syms[i].st_shndx) continue;67 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;
69 if (maybe_versym) |versym| {70 if (maybe_versym) |versym| {
70 if (!checkver(maybe_verdef.?, versym[i], vername, strings))71 if (!checkver(maybe_verdef.?, versym[i], vername, strings))
71 continue;72 continue;
...@@ -87,5 +88,6 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [...@@ -87,5 +88,6 @@ fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [
87 def = @intToPtr(*elf.Verdef, @ptrToInt(def) + def.vd_next);88 def = @intToPtr(*elf.Verdef, @ptrToInt(def) + def.vd_next);
88 }89 }
89 const aux = @intToPtr(*elf.Verdaux, @ptrToInt(def) + def.vd_aux);90 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));
91}93}
lib/std/os/wasi.zig+2-2
...@@ -19,13 +19,13 @@ comptime {...@@ -19,13 +19,13 @@ comptime {
19pub const iovec_t = iovec;19pub const iovec_t = iovec;
20pub const ciovec_t = iovec_const;20pub 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;
23pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;23pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t;
2424
25pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t;25pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t;
26pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t;26pub 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;
29pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t;29pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t;
3030
31pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t;31pub 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{...@@ -192,7 +192,7 @@ pub const FindFirstFileError = error{
192};192};
193193
194pub fn FindFirstFile(dir_path: []const u8, find_file_data: *WIN32_FIND_DATAW) FindFirstFileError!HANDLE {194pub 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{ '\\', '*'});
196 const handle = kernel32.FindFirstFileW(&dir_path_w, find_file_data);196 const handle = kernel32.FindFirstFileW(&dir_path_w, find_file_data);
197197
198 if (handle == INVALID_HANDLE_VALUE) {198 if (handle == INVALID_HANDLE_VALUE) {
...@@ -919,18 +919,18 @@ pub fn nanoSecondsToFileTime(ns: i64) FILETIME {...@@ -919,18 +919,18 @@ pub fn nanoSecondsToFileTime(ns: i64) FILETIME {
919 };919 };
920}920}
921921
922pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 {922pub fn cStrToPrefixedFileW(s: [*:0]const u8) ![PATH_MAX_WIDE:0]u16 {
923 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));923 return sliceToPrefixedFileW(mem.toSliceConst(u8, s));
924}924}
925925
926pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 {926pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE:0]u16 {
927 return sliceToPrefixedSuffixedFileW(s, [_]u16{0});927 return sliceToPrefixedSuffixedFileW(s, &[_]u16{});
928}928}
929929
930/// Assumes an absolute path.930/// 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 {
932 // TODO https://github.com/ziglang/zig/issues/2765932 // 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
935 const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: {935 const start_index = if (mem.startsWith(u16, s, [_]u16{'\\', '?'})) 0 else blk: {
936 const prefix = [_]u16{ '\\', '?', '?', '\\' };936 const prefix = [_]u16{ '\\', '?', '?', '\\' };
...@@ -945,9 +945,9 @@ pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {...@@ -945,9 +945,9 @@ pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 {
945945
946}946}
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 {
949 // TODO https://github.com/ziglang/zig/issues/2765949 // 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;
951 // > File I/O functions in the Windows API convert "/" to "\" as part of951 // > File I/O functions in the Windows API convert "/" to "\" as part of
952 // > converting the name to an NT-style name, except when using the "\\?\"952 // > converting the name to an NT-style name, except when using the "\\?\"
953 // > prefix as detailed in the following sections.953 // > prefix as detailed in the following sections.
...@@ -968,6 +968,7 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)...@@ -968,6 +968,7 @@ pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16)
968 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);968 const end_index = start_index + try std.unicode.utf8ToUtf16Le(result[start_index..], s);
969 if (end_index + suffix.len > result.len) return error.NameTooLong;969 if (end_index + suffix.len > result.len) return error.NameTooLong;
970 mem.copy(u16, result[end_index..], suffix);970 mem.copy(u16, result[end_index..], suffix);
971 result[end_index + suffix.len] = 0;
971 return result;972 return result;
972}973}
973974
lib/std/process.zig+10-10
...@@ -77,7 +77,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {...@@ -77,7 +77,7 @@ pub fn getEnvMap(allocator: *Allocator) !BufMap {
7777
78 // TODO: Verify that the documentation is incorrect78 // TODO: Verify that the documentation is incorrect
79 // https://github.com/WebAssembly/WASI/issues/2779 // 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);
81 defer allocator.free(environ);81 defer allocator.free(environ);
82 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);82 var environ_buf = try std.heap.wasm_allocator.alloc(u8, environ_buf_size);
83 defer allocator.free(environ_buf);83 defer allocator.free(environ_buf);
...@@ -397,7 +397,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {...@@ -397,7 +397,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 {
397 return os.unexpectedErrno(args_sizes_get_ret);397 return os.unexpectedErrno(args_sizes_get_ret);
398 }398 }
399399
400 var argv = try allocator.alloc([*]u8, count);400 var argv = try allocator.alloc([*:0]u8, count);
401 defer allocator.free(argv);401 defer allocator.free(argv);
402402
403 var argv_buf = try allocator.alloc(u8, buf_size);403 var argv_buf = try allocator.alloc(u8, buf_size);
...@@ -473,14 +473,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {...@@ -473,14 +473,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
473}473}
474474
475test "windows arg parsing" {475test "windows arg parsing" {
476 testWindowsCmdLine(c"a b\tc d", [_][]const u8{ "a", "b", "c", "d" });476 testWindowsCmdLine("a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
477 testWindowsCmdLine(c"\"abc\" d e", [_][]const u8{ "abc", "d", "e" });477 testWindowsCmdLine("\"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" });478 testWindowsCmdLine("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" });479 testWindowsCmdLine("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" });480 testWindowsCmdLine("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" });481 testWindowsCmdLine("a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
482482
483 testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{483 testWindowsCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
484 ".\\..\\zig-cache\\build",484 ".\\..\\zig-cache\\build",
485 "bin\\zig.exe",485 "bin\\zig.exe",
486 ".\\..",486 ".\\..",
lib/std/special/c.zig+5-5
...@@ -66,14 +66,14 @@ extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {...@@ -66,14 +66,14 @@ extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {
66}66}
6767
68extern fn strerror(errnum: c_int) [*]const u8 {68extern fn strerror(errnum: c_int) [*]const u8 {
69 return c"TODO strerror implementation";69 return "TODO strerror implementation";
70}70}
7171
72test "strncmp" {72test "strncmp" {
73 std.testing.expect(strncmp(c"a", c"b", 1) == -1);73 std.testing.expect(strncmp("a", "b", 1) == -1);
74 std.testing.expect(strncmp(c"a", c"c", 1) == -2);74 std.testing.expect(strncmp("a", "c", 1) == -2);
75 std.testing.expect(strncmp(c"b", c"a", 1) == 1);75 std.testing.expect(strncmp("b", "a", 1) == 1);
76 std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253);76 std.testing.expect(strncmp("\xff", "\x02", 1) == 253);
77}77}
7878
79// Avoid dragging in the runtime safety mechanisms into this .o file,79// 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 {...@@ -123,12 +123,12 @@ fn posixCallMainAndExit() noreturn {
123 @setAlignStack(16);123 @setAlignStack(16);
124 }124 }
125 const argc = starting_stack_ptr[0];125 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);
129 var envp_count: usize = 0;129 var envp_count: usize = 0;
130 while (envp_optional[envp_count]) |_| : (envp_count += 1) {}130 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
133 if (builtin.os == .linux) {133 if (builtin.os == .linux) {
134 // Find the beginning of the auxiliary vector134 // Find the beginning of the auxiliary vector
...@@ -168,7 +168,7 @@ fn posixCallMainAndExit() noreturn {...@@ -168,7 +168,7 @@ fn posixCallMainAndExit() noreturn {
168 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));168 std.os.exit(@inlineCall(callMainWithArgs, argc, argv, envp));
169}169}
170170
171fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {171fn callMainWithArgs(argc: usize, argv: [*][*:0]u8, envp: [][*:0]u8) u8 {
172 std.os.argv = argv[0..argc];172 std.os.argv = argv[0..argc];
173 std.os.environ = envp;173 std.os.environ = envp;
174174
...@@ -177,10 +177,10 @@ fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {...@@ -177,10 +177,10 @@ fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 {
177 return initEventLoopAndCallMain();177 return initEventLoopAndCallMain();
178}178}
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 {
181 var env_count: usize = 0;181 var env_count: usize = 0;
182 while (c_envp[env_count] != null) : (env_count += 1) {}182 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];
184 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);184 return @inlineCall(callMainWithArgs, @intCast(usize, c_argc), c_argv, envp);
185}185}
186186
lib/std/special/test_runner.zig+1-1
...@@ -36,7 +36,7 @@ pub fn main() anyerror!void {...@@ -36,7 +36,7 @@ pub fn main() anyerror!void {
36 }36 }
37 root_node.end();37 root_node.end();
38 if (ok_count == test_fn_list.len) {38 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);
40 } else {40 } else {
41 std.debug.warn("{} passed; {} skipped.\n", ok_count, skip_count);41 std.debug.warn("{} passed; {} skipped.\n", ok_count, skip_count);
42 }42 }
lib/std/thread.zig+1-1
...@@ -353,7 +353,7 @@ pub const Thread = struct {...@@ -353,7 +353,7 @@ pub const Thread = struct {
353 }353 }
354 var count: c_int = undefined;354 var count: c_int = undefined;
355 var count_len: usize = @sizeOf(c_int);355 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";
357 os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {357 os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {
358 error.NameTooLong => unreachable,358 error.NameTooLong => unreachable,
359 else => |e| return e,359 else => |e| return e,
lib/std/valgrind/memcheck.zig+1-1
...@@ -3,7 +3,7 @@ const testing = std.testing;...@@ -3,7 +3,7 @@ const testing = std.testing;
3const valgrind = std.valgrind;3const valgrind = std.valgrind;
44
5pub const MemCheckClientRequest = extern enum {5pub const MemCheckClientRequest = extern enum {
6 MakeMemNoAccess = valgrind.ToolBase("MC"),6 MakeMemNoAccess = valgrind.ToolBase("MC".*),
7 MakeMemUndefined,7 MakeMemUndefined,
8 MakeMemDefined,8 MakeMemDefined,
9 Discard,9 Discard,
lib/std/zig/ast.zig+23-8
...@@ -1531,14 +1531,14 @@ pub const Node = struct {...@@ -1531,14 +1531,14 @@ pub const Node = struct {
1531 };1531 };
15321532
1533 pub const PrefixOp = struct {1533 pub const PrefixOp = struct {
1534 base: Node,1534 base: Node = Node{ .id = .PrefixOp },
1535 op_token: TokenIndex,1535 op_token: TokenIndex,
1536 op: Op,1536 op: Op,
1537 rhs: *Node,1537 rhs: *Node,
15381538
1539 pub const Op = union(enum) {1539 pub const Op = union(enum) {
1540 AddressOf,1540 AddressOf,
1541 ArrayType: *Node,1541 ArrayType: ArrayInfo,
1542 Await,1542 Await,
1543 BitNot,1543 BitNot,
1544 BoolNot,1544 BoolNot,
...@@ -1552,11 +1552,17 @@ pub const Node = struct {...@@ -1552,11 +1552,17 @@ pub const Node = struct {
1552 Try,1552 Try,
1553 };1553 };
15541554
1555 pub const ArrayInfo = struct {
1556 len_expr: *Node,
1557 sentinel: ?*Node,
1558 };
1559
1555 pub const PtrInfo = struct {1560 pub const PtrInfo = struct {
1556 allowzero_token: ?TokenIndex,1561 allowzero_token: ?TokenIndex = null,
1557 align_info: ?Align,1562 align_info: ?Align = null,
1558 const_token: ?TokenIndex,1563 const_token: ?TokenIndex = null,
1559 volatile_token: ?TokenIndex,1564 volatile_token: ?TokenIndex = null,
1565 sentinel: ?*Node = null,
15601566
1561 pub const Align = struct {1567 pub const Align = struct {
1562 node: *Node,1568 node: *Node,
...@@ -1575,6 +1581,11 @@ pub const Node = struct {...@@ -1575,6 +1581,11 @@ pub const Node = struct {
1575 switch (self.op) {1581 switch (self.op) {
1576 // TODO https://github.com/ziglang/zig/issues/11071582 // TODO https://github.com/ziglang/zig/issues/1107
1577 Op.SliceType => |addr_of_info| {1583 Op.SliceType => |addr_of_info| {
1584 if (addr_of_info.sentinel) |sentinel| {
1585 if (i < 1) return sentinel;
1586 i -= 1;
1587 }
1588
1578 if (addr_of_info.align_info) |align_info| {1589 if (addr_of_info.align_info) |align_info| {
1579 if (i < 1) return align_info.node;1590 if (i < 1) return align_info.node;
1580 i -= 1;1591 i -= 1;
...@@ -1588,9 +1599,13 @@ pub const Node = struct {...@@ -1588,9 +1599,13 @@ pub const Node = struct {
1588 }1599 }
1589 },1600 },
15901601
1591 Op.ArrayType => |size_expr| {1602 Op.ArrayType => |array_info| {
1592 if (i < 1) return size_expr;1603 if (i < 1) return array_info.len_expr;
1593 i -= 1;1604 i -= 1;
1605 if (array_info.sentinel) |sentinel| {
1606 if (i < 1) return sentinel;
1607 i -= 1;
1608 }
1594 },1609 },
15951610
1596 Op.AddressOf,1611 Op.AddressOf,
lib/std/zig/parse.zig+139-98
...@@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf...@@ -1085,7 +1085,7 @@ fn parseInitList(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node.Suf
1085 const node = try arena.create(Node.SuffixOp);1085 const node = try arena.create(Node.SuffixOp);
1086 node.* = Node.SuffixOp{1086 node.* = Node.SuffixOp{
1087 .base = Node{ .id = .SuffixOp },1087 .base = Node{ .id = .SuffixOp },
1088 .lhs = .{.node = undefined}, // set by caller1088 .lhs = .{ .node = undefined }, // set by caller
1089 .op = op,1089 .op = op,
1090 .rtoken = try expectToken(it, tree, .RBrace),1090 .rtoken = try expectToken(it, tree, .RBrace),
1091 };1091 };
...@@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1138,7 +1138,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
11381138
1139 while (try parseSuffixOp(arena, it, tree)) |node| {1139 while (try parseSuffixOp(arena, it, tree)) |node| {
1140 switch (node.id) {1140 switch (node.id) {
1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},1141 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
1142 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1142 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1143 else => unreachable,1143 else => unreachable,
1144 }1144 }
...@@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1154,7 +1154,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1154 const node = try arena.create(Node.SuffixOp);1154 const node = try arena.create(Node.SuffixOp);
1155 node.* = Node.SuffixOp{1155 node.* = Node.SuffixOp{
1156 .base = Node{ .id = .SuffixOp },1156 .base = Node{ .id = .SuffixOp },
1157 .lhs = .{.node = res},1157 .lhs = .{ .node = res },
1158 .op = Node.SuffixOp.Op{1158 .op = Node.SuffixOp.Op{
1159 .Call = Node.SuffixOp.Op.Call{1159 .Call = Node.SuffixOp.Op.Call{
1160 .params = params.list,1160 .params = params.list,
...@@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1171,7 +1171,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1171 while (true) {1171 while (true) {
1172 if (try parseSuffixOp(arena, it, tree)) |node| {1172 if (try parseSuffixOp(arena, it, tree)) |node| {
1173 switch (node.id) {1173 switch (node.id) {
1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{.node = res},1174 .SuffixOp => node.cast(Node.SuffixOp).?.lhs = .{ .node = res },
1175 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,1175 .InfixOp => node.cast(Node.InfixOp).?.lhs = res,
1176 else => unreachable,1176 else => unreachable,
1177 }1177 }
...@@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -1182,7 +1182,7 @@ fn parseSuffixExpr(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
1182 const call = try arena.create(Node.SuffixOp);1182 const call = try arena.create(Node.SuffixOp);
1183 call.* = Node.SuffixOp{1183 call.* = Node.SuffixOp{
1184 .base = Node{ .id = .SuffixOp },1184 .base = Node{ .id = .SuffixOp },
1185 .lhs = .{.node = res},1185 .lhs = .{ .node = res },
1186 .op = Node.SuffixOp.Op{1186 .op = Node.SuffixOp.Op{
1187 .Call = Node.SuffixOp.Op.Call{1187 .Call = Node.SuffixOp.Op.Call{
1188 .params = params.list,1188 .params = params.list,
...@@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -1531,7 +1531,7 @@ fn parseAnonLiteral(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
15311531
1532 // anon container literal1532 // anon container literal
1533 if (try parseInitList(arena, it, tree)) |node| {1533 if (try parseInitList(arena, it, tree)) |node| {
1534 node.lhs = .{.dot = dot};1534 node.lhs = .{ .dot = dot };
1535 return &node.base;1535 return &node.base;
1536 }1536 }
15371537
...@@ -2246,63 +2246,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2246,63 +2246,6 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2246 return &node.base;2246 return &node.base;
2247 }2247 }
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
2306 if (try parsePtrTypeStart(arena, it, tree)) |node| {2249 if (try parsePtrTypeStart(arena, it, tree)) |node| {
2307 // If the token encountered was **, there will be two nodes instead of one.2250 // If the token encountered was **, there will be two nodes instead of one.
2308 // The attributes should be applied to the rightmost operator.2251 // The attributes should be applied to the rightmost operator.
...@@ -2361,6 +2304,63 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node...@@ -2361,6 +2304,63 @@ fn parsePrefixTypeOp(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node
2361 return node;2304 return node;
2362 }2305 }
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
2364 return null;2364 return null;
2365}2365}
23662366
...@@ -2459,10 +2459,21 @@ const AnnotatedParamList = struct {...@@ -2459,10 +2459,21 @@ const AnnotatedParamList = struct {
2459fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2459fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2460 const lbracket = eatToken(it, .LBracket) orelse return null;2460 const lbracket = eatToken(it, .LBracket) orelse return null;
2461 const expr = try parseExpr(arena, it, tree);2461 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;
2462 const rbracket = try expectToken(it, tree, .RBracket);2468 const rbracket = try expectToken(it, tree, .RBracket);
24632469
2464 const op = if (expr) |element_type|2470 const op = if (expr) |len_expr|
2465 Node.PrefixOp.Op{ .ArrayType = element_type }2471 Node.PrefixOp.Op{
2472 .ArrayType = .{
2473 .len_expr = len_expr,
2474 .sentinel = sentinel,
2475 },
2476 }
2466 else2477 else
2467 Node.PrefixOp.Op{2478 Node.PrefixOp.Op{
2468 .SliceType = Node.PrefixOp.PtrInfo{2479 .SliceType = Node.PrefixOp.PtrInfo{
...@@ -2470,6 +2481,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2470,6 +2481,7 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2470 .align_info = null,2481 .align_info = null,
2471 .const_token = null,2482 .const_token = null,
2472 .volatile_token = null,2483 .volatile_token = null,
2484 .sentinel = sentinel,
2473 },2485 },
2474 };2486 };
24752487
...@@ -2489,47 +2501,76 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -2489,47 +2501,76 @@ fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
2489/// / PTRUNKNOWN2501/// / PTRUNKNOWN
2490/// / PTRC2502/// / PTRC
2491fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {2503fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
2492 const token = eatAnnotatedToken(it, .Asterisk) orelse2504 if (eatToken(it, .Asterisk)) |asterisk| {
2493 eatAnnotatedToken(it, .AsteriskAsterisk) orelse2505 const sentinel = if (eatToken(it, .Colon)) |_|
2494 eatAnnotatedToken(it, .BracketStarBracket) orelse2506 try expectNode(arena, it, tree, parseExpr, AstError{
2495 eatAnnotatedToken(it, .BracketStarCBracket) orelse2507 .ExpectedExpr = .{ .token = it.index },
2496 return null;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);2520 if (eatToken(it, .AsteriskAsterisk)) |double_asterisk| {
2499 node.* = Node.PrefixOp{2521 const node = try arena.create(Node.PrefixOp);
2500 .base = Node{ .id = .PrefixOp },2522 node.* = Node.PrefixOp{
2501 .op_token = token.index,2523 .op_token = double_asterisk,
2502 .op = Node.PrefixOp.Op{2524 .op = Node.PrefixOp.Op{ .PtrType = .{} },
2503 .PtrType = Node.PrefixOp.PtrInfo{2525 .rhs = undefined, // set by caller
2504 .allowzero_token = null,2526 };
2505 .align_info = null,
2506 .const_token = null,
2507 .volatile_token = null,
2508 },
2509 },
2510 .rhs = undefined, // set by caller
2511 };
25122527
2513 // Special case for **, which is its own token2528 // Special case for **, which is its own token
2514 if (token.ptr.id == .AsteriskAsterisk) {
2515 const child = try arena.create(Node.PrefixOp);2529 const child = try arena.create(Node.PrefixOp);
2516 child.* = Node.PrefixOp{2530 child.* = Node.PrefixOp{
2517 .base = Node{ .id = .PrefixOp },2531 .op_token = double_asterisk,
2518 .op_token = token.index,2532 .op = Node.PrefixOp.Op{ .PtrType = .{} },
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 },
2527 .rhs = undefined, // set by caller2533 .rhs = undefined, // set by caller
2528 };2534 };
2529 node.rhs = &child.base;2535 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;
2533}2574}
25342575
2535/// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE2576/// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
lib/std/zig/parser_test.zig+3-6
...@@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" {...@@ -1552,6 +1552,7 @@ test "zig fmt: pointer attributes" {
1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1552 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1553 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;1554 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1555 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
1555 \\1556 \\
1556 );1557 );
1557}1558}
...@@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" {...@@ -1562,6 +1563,7 @@ test "zig fmt: slice attributes" {
1562 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;1563 \\extern fn f2(s: **align(1) *const *volatile u8) c_int;
1563 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;1564 \\extern fn f3(s: *align(1) const *align(1) volatile *const volatile u8) c_int;
1564 \\extern fn f4(s: *align(1) const volatile u8) c_int;1565 \\extern fn f4(s: *align(1) const volatile u8) c_int;
1566 \\extern fn f5(s: [*:0]align(1) const volatile u8) c_int;
1565 \\1567 \\
1566 );1568 );
1567}1569}
...@@ -1723,11 +1725,6 @@ test "zig fmt: multiline string" {...@@ -1723,11 +1725,6 @@ test "zig fmt: multiline string" {
1723 \\ \\two)1725 \\ \\two)
1724 \\ \\three1726 \\ \\three
1725 \\ ;1727 \\ ;
1726 \\ const s2 =
1727 \\ c\\one
1728 \\ c\\two)
1729 \\ c\\three
1730 \\ ;
1731 \\ const s3 = // hi1728 \\ const s3 = // hi
1732 \\ \\one1729 \\ \\one
1733 \\ \\two)1730 \\ \\two)
...@@ -1744,7 +1741,6 @@ test "zig fmt: values" {...@@ -1744,7 +1741,6 @@ test "zig fmt: values" {
1744 \\ 1;1741 \\ 1;
1745 \\ 1.0;1742 \\ 1.0;
1746 \\ "string";1743 \\ "string";
1747 \\ c"cstring";
1748 \\ 'c';1744 \\ 'c';
1749 \\ true;1745 \\ true;
1750 \\ false;1746 \\ false;
...@@ -1889,6 +1885,7 @@ test "zig fmt: arrays" {...@@ -1889,6 +1885,7 @@ test "zig fmt: arrays" {
1889 \\ 2,1885 \\ 2,
1890 \\ };1886 \\ };
1891 \\ const a: [0]u8 = []u8{};1887 \\ const a: [0]u8 = []u8{};
1888 \\ const x: [4:0]u8 = undefined;
1892 \\}1889 \\}
1893 \\1890 \\
1894 );1891 );
lib/std/zig/render.zig+32-8
...@@ -418,11 +418,27 @@ fn renderExpression(...@@ -418,11 +418,27 @@ fn renderExpression(
418418
419 switch (prefix_op_node.op) {419 switch (prefix_op_node.op) {
420 ast.Node.PrefixOp.Op.PtrType => |ptr_info| {420 ast.Node.PrefixOp.Op.PtrType => |ptr_info| {
421 const star_offset = switch (tree.tokens.at(prefix_op_node.op_token).id) {421 const op_tok_id = tree.tokens.at(prefix_op_node.op_token).id;
422 Token.Id.AsteriskAsterisk => @as(usize, 1),422 switch (op_tok_id) {
423 else => @as(usize, 0),423 .Asterisk, .AsteriskAsterisk => try stream.writeByte('*'),
424 };424 .Identifier => try stream.write("[*c]"),
425 try renderTokenOffset(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None, star_offset); // *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 }
426 if (ptr_info.allowzero_token) |allowzero_token| {442 if (ptr_info.allowzero_token) |allowzero_token| {
427 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero443 try renderToken(tree, stream, allowzero_token, indent, start_col, Space.Space); // allowzero
428 }444 }
...@@ -499,9 +515,12 @@ fn renderExpression(...@@ -499,9 +515,12 @@ fn renderExpression(
499 }515 }
500 },516 },
501517
502 ast.Node.PrefixOp.Op.ArrayType => |array_index| {518 ast.Node.PrefixOp.Op.ArrayType => |array_info| {
503 const lbracket = prefix_op_node.op_token;519 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
506 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [525 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
507526
...@@ -509,13 +528,18 @@ fn renderExpression(...@@ -509,13 +528,18 @@ fn renderExpression(
509 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;528 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;
510 const new_indent = if (ends_with_comment) indent + indent_delta else indent;529 const new_indent = if (ends_with_comment) indent + indent_delta else indent;
511 const new_space = if (ends_with_comment) Space.Newline else Space.None;530 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);
513 if (starts_with_comment) {532 if (starts_with_comment) {
514 try stream.writeByte('\n');533 try stream.writeByte('\n');
515 }534 }
516 if (ends_with_comment or starts_with_comment) {535 if (ends_with_comment or starts_with_comment) {
517 try stream.writeByteNTimes(' ', indent);536 try stream.writeByteNTimes(' ', indent);
518 }537 }
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 }
519 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]543 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]
520 },544 },
521 ast.Node.PrefixOp.Op.BitNot,545 ast.Node.PrefixOp.Op.BitNot,
lib/std/zig/tokenizer.zig+11-73
...@@ -143,8 +143,6 @@ pub const Token = struct {...@@ -143,8 +143,6 @@ pub const Token = struct {
143 LineComment,143 LineComment,
144 DocComment,144 DocComment,
145 ContainerDocComment,145 ContainerDocComment,
146 BracketStarBracket,
147 BracketStarCBracket,
148 ShebangLine,146 ShebangLine,
149 Keyword_align,147 Keyword_align,
150 Keyword_allowzero,148 Keyword_allowzero,
...@@ -269,8 +267,6 @@ pub const Token = struct {...@@ -269,8 +267,6 @@ pub const Token = struct {
269 .AngleBracketAngleBracketRight => ">>",267 .AngleBracketAngleBracketRight => ">>",
270 .AngleBracketAngleBracketRightEqual => ">>=",268 .AngleBracketAngleBracketRightEqual => ">>=",
271 .Tilde => "~",269 .Tilde => "~",
272 .BracketStarBracket => "[*]",
273 .BracketStarCBracket => "[*c]",
274 .Keyword_align => "align",270 .Keyword_align => "align",
275 .Keyword_allowzero => "allowzero",271 .Keyword_allowzero => "allowzero",
276 .Keyword_and => "and",272 .Keyword_and => "and",
...@@ -351,7 +347,6 @@ pub const Tokenizer = struct {...@@ -351,7 +347,6 @@ pub const Tokenizer = struct {
351 Start,347 Start,
352 Identifier,348 Identifier,
353 Builtin,349 Builtin,
354 C,
355 StringLiteral,350 StringLiteral,
356 StringLiteralBackslash,351 StringLiteralBackslash,
357 MultilineStringLiteralLine,352 MultilineStringLiteralLine,
...@@ -401,9 +396,6 @@ pub const Tokenizer = struct {...@@ -401,9 +396,6 @@ pub const Tokenizer = struct {
401 Period,396 Period,
402 Period2,397 Period2,
403 SawAtSign,398 SawAtSign,
404 LBracket,
405 LBracketStar,
406 LBracketStarC,
407 };399 };
408400
409 pub fn next(self: *Tokenizer) Token {401 pub fn next(self: *Tokenizer) Token {
...@@ -427,10 +419,6 @@ pub const Tokenizer = struct {...@@ -427,10 +419,6 @@ pub const Tokenizer = struct {
427 ' ', '\n', '\t', '\r' => {419 ' ', '\n', '\t', '\r' => {
428 result.start = self.index + 1;420 result.start = self.index + 1;
429 },421 },
430 'c' => {
431 state = State.C;
432 result.id = Token.Id.Identifier;
433 },
434 '"' => {422 '"' => {
435 state = State.StringLiteral;423 state = State.StringLiteral;
436 result.id = Token.Id.StringLiteral;424 result.id = Token.Id.StringLiteral;
...@@ -438,7 +426,7 @@ pub const Tokenizer = struct {...@@ -438,7 +426,7 @@ pub const Tokenizer = struct {
438 '\'' => {426 '\'' => {
439 state = State.CharLiteral;427 state = State.CharLiteral;
440 },428 },
441 'a'...'b', 'd'...'z', 'A'...'Z', '_' => {429 'a'...'z', 'A'...'Z', '_' => {
442 state = State.Identifier;430 state = State.Identifier;
443 result.id = Token.Id.Identifier;431 result.id = Token.Id.Identifier;
444 },432 },
...@@ -465,7 +453,9 @@ pub const Tokenizer = struct {...@@ -465,7 +453,9 @@ pub const Tokenizer = struct {
465 break;453 break;
466 },454 },
467 '[' => {455 '[' => {
468 state = State.LBracket;456 result.id = .LBracket;
457 self.index += 1;
458 break;
469 },459 },
470 ']' => {460 ']' => {
471 result.id = Token.Id.RBracket;461 result.id = Token.Id.RBracket;
...@@ -569,43 +559,6 @@ pub const Tokenizer = struct {...@@ -569,43 +559,6 @@ pub const Tokenizer = struct {
569 },559 },
570 },560 },
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
609 State.Ampersand => switch (c) {562 State.Ampersand => switch (c) {
610 '&' => {563 '&' => {
611 result.id = Token.Id.Invalid_ampersands;564 result.id = Token.Id.Invalid_ampersands;
...@@ -730,20 +683,6 @@ pub const Tokenizer = struct {...@@ -730,20 +683,6 @@ pub const Tokenizer = struct {
730 },683 },
731 else => break,684 else => break,
732 },685 },
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 },
747 State.StringLiteral => switch (c) {686 State.StringLiteral => switch (c) {
748 '\\' => {687 '\\' => {
749 state = State.StringLiteralBackslash;688 state = State.StringLiteralBackslash;
...@@ -1204,7 +1143,6 @@ pub const Tokenizer = struct {...@@ -1204,7 +1143,6 @@ pub const Tokenizer = struct {
1204 } else if (self.index == self.buffer.len) {1143 } else if (self.index == self.buffer.len) {
1205 switch (state) {1144 switch (state) {
1206 State.Start,1145 State.Start,
1207 State.C,
1208 State.IntegerLiteral,1146 State.IntegerLiteral,
1209 State.IntegerLiteralWithRadix,1147 State.IntegerLiteralWithRadix,
1210 State.IntegerLiteralWithRadixHex,1148 State.IntegerLiteralWithRadixHex,
...@@ -1247,8 +1185,6 @@ pub const Tokenizer = struct {...@@ -1247,8 +1185,6 @@ pub const Tokenizer = struct {
1247 State.CharLiteralEnd,1185 State.CharLiteralEnd,
1248 State.CharLiteralUnicode,1186 State.CharLiteralUnicode,
1249 State.StringLiteralBackslash,1187 State.StringLiteralBackslash,
1250 State.LBracketStar,
1251 State.LBracketStarC,
1252 => {1188 => {
1253 result.id = Token.Id.Invalid;1189 result.id = Token.Id.Invalid;
1254 },1190 },
...@@ -1265,9 +1201,6 @@ pub const Tokenizer = struct {...@@ -1265,9 +1201,6 @@ pub const Tokenizer = struct {
1265 State.Slash => {1201 State.Slash => {
1266 result.id = Token.Id.Slash;1202 result.id = Token.Id.Slash;
1267 },1203 },
1268 State.LBracket => {
1269 result.id = Token.Id.LBracket;
1270 },
1271 State.Zero => {1204 State.Zero => {
1272 result.id = Token.Id.IntegerLiteral;1205 result.id = Token.Id.IntegerLiteral;
1273 },1206 },
...@@ -1388,9 +1321,14 @@ test "tokenizer - unknown length pointer and then c pointer" {...@@ -1388,9 +1321,14 @@ test "tokenizer - unknown length pointer and then c pointer" {
1388 \\[*]u81321 \\[*]u8
1389 \\[*c]u81322 \\[*c]u8
1390 , [_]Token.Id{1323 , [_]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,
1392 Token.Id.Identifier,1330 Token.Id.Identifier,
1393 Token.Id.BracketStarCBracket,1331 Token.Id.RBracket,
1394 Token.Id.Identifier,1332 Token.Id.Identifier,
1395 });1333 });
1396}1334}
src-self-hosted/clang.zig+3-3
...@@ -708,7 +708,7 @@ pub const ZigClangStringLiteral_StringKind = extern enum {...@@ -708,7 +708,7 @@ pub const ZigClangStringLiteral_StringKind = extern enum {
708};708};
709709
710pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;710pub 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;
712pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;712pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
713pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;713pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
714pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;714pub 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...@@ -746,7 +746,7 @@ pub extern fn ZigClangQualType_isRestrictQualified(self: struct_ZigClangQualType
746pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;746pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
747pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;747pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
748pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;748pub 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;
750pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;750pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
751pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;751pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass;
752pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;752pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
...@@ -904,7 +904,7 @@ pub extern fn ZigClangLoadFromCommandLine(...@@ -904,7 +904,7 @@ pub extern fn ZigClangLoadFromCommandLine(
904) ?*ZigClangASTUnit;904) ?*ZigClangASTUnit;
905905
906pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;906pub 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
909pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt;909pub 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)...@@ -52,7 +52,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
52 u32(c.ZIG_VERSION_MINOR),52 u32(c.ZIG_VERSION_MINOR),
53 u32(c.ZIG_VERSION_PATCH),53 u32(c.ZIG_VERSION_PATCH),
54 );54 );
55 const flags = c"";55 const flags = "";
56 const runtime_version = 0;56 const runtime_version = 0;
57 const compile_unit_file = llvm.CreateFile(57 const compile_unit_file = llvm.CreateFile(
58 dibuilder,58 dibuilder,
...@@ -68,7 +68,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)...@@ -68,7 +68,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
68 is_optimized,68 is_optimized,
69 flags,69 flags,
70 runtime_version,70 runtime_version,
71 c"",71 "",
72 0,72 0,
73 !comp.strip,73 !comp.strip,
74 ) orelse return error.OutOfMemory;74 ) orelse return error.OutOfMemory;
...@@ -402,7 +402,7 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Poin...@@ -402,7 +402,7 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Poin
402 if (child_type.handleIsPtr()) {402 if (child_type.handleIsPtr()) {
403 return ptr;403 return ptr;
404 }404 }
405 return try renderLoad(ofile, ptr, ptr_type, c"");405 return try renderLoad(ofile, ptr, ptr_type, "");
406}406}
407407
408pub fn renderStoreUntyped(408pub fn renderStoreUntyped(
src-self-hosted/compilation.zig+5-5
...@@ -490,8 +490,8 @@ pub const Compilation = struct {...@@ -490,8 +490,8 @@ pub const Compilation = struct {
490 // LLVM creates invalid binaries on Windows sometimes.490 // LLVM creates invalid binaries on Windows sometimes.
491 // See https://github.com/ziglang/zig/issues/508491 // See https://github.com/ziglang/zig/issues/508
492 // As a workaround we do not use target native features on Windows.492 // As a workaround we do not use target native features on Windows.
493 var target_specific_cpu_args: ?[*]u8 = null;493 var target_specific_cpu_args: ?[*:0]u8 = null;
494 var target_specific_cpu_features: ?[*]u8 = null;494 var target_specific_cpu_features: ?[*:0]u8 = null;
495 defer llvm.DisposeMessage(target_specific_cpu_args);495 defer llvm.DisposeMessage(target_specific_cpu_args);
496 defer llvm.DisposeMessage(target_specific_cpu_features);496 defer llvm.DisposeMessage(target_specific_cpu_features);
497 if (target == Target.Native and !target.isWindows()) {497 if (target == Target.Native and !target.isWindows()) {
...@@ -501,9 +501,9 @@ pub const Compilation = struct {...@@ -501,9 +501,9 @@ pub const Compilation = struct {
501501
502 comp.target_machine = llvm.CreateTargetMachine(502 comp.target_machine = llvm.CreateTargetMachine(
503 comp.llvm_target,503 comp.llvm_target,
504 comp.llvm_triple.ptr(),504 comp.llvm_triple.toSliceConst(),
505 target_specific_cpu_args orelse c"",505 target_specific_cpu_args orelse "",
506 target_specific_cpu_features orelse c"",506 target_specific_cpu_features orelse "",
507 opt_level,507 opt_level,
508 reloc_mode,508 reloc_mode,
509 llvm.CodeModelDefault,509 llvm.CodeModelDefault,
src-self-hosted/ir.zig+6-6
...@@ -330,7 +330,7 @@ pub const Inst = struct {...@@ -330,7 +330,7 @@ pub const Inst = struct {
330 @intCast(c_uint, args.len),330 @intCast(c_uint, args.len),
331 llvm_cc,331 llvm_cc,
332 fn_inline,332 fn_inline,
333 c"",333 "",
334 ) orelse error.OutOfMemory;334 ) orelse error.OutOfMemory;
335 }335 }
336 };336 };
...@@ -1409,7 +1409,7 @@ pub const Builder = struct {...@@ -1409,7 +1409,7 @@ pub const Builder = struct {
1409 if (block.label) |label| {1409 if (block.label) |label| {
1410 block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena());1410 block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena());
1411 block_scope.incoming_blocks = std.ArrayList(*BasicBlock).init(irb.arena());1411 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");
1413 block_scope.is_comptime = try irb.buildConstBool(1413 block_scope.is_comptime = try irb.buildConstBool(
1414 parent_scope,1414 parent_scope,
1415 Span.token(block.lbrace),1415 Span.token(block.lbrace),
...@@ -1541,8 +1541,8 @@ pub const Builder = struct {...@@ -1541,8 +1541,8 @@ pub const Builder = struct {
1541 const defer_counts = irb.countDefers(scope, outer_scope);1541 const defer_counts = irb.countDefers(scope, outer_scope);
1542 const have_err_defers = defer_counts.error_exit != 0;1542 const have_err_defers = defer_counts.error_exit != 0;
1543 if (have_err_defers or irb.comp.have_err_ret_tracing) {1543 if (have_err_defers or irb.comp.have_err_ret_tracing) {
1544 const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");1544 const err_block = try irb.createBasicBlock(scope, "ErrRetErr");
1545 const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");1545 const ok_block = try irb.createBasicBlock(scope, "ErrRetOk");
1546 if (!have_err_defers) {1546 if (!have_err_defers) {
1547 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);1547 _ = try irb.genDefersForBlock(scope, outer_scope, .ScopeExit);
1548 }1548 }
...@@ -1563,7 +1563,7 @@ pub const Builder = struct {...@@ -1563,7 +1563,7 @@ pub const Builder = struct {
1563 .is_comptime = err_is_comptime,1563 .is_comptime = err_is_comptime,
1564 });1564 });
15651565
1566 const ret_stmt_block = try irb.createBasicBlock(scope, c"RetStmt");1566 const ret_stmt_block = try irb.createBasicBlock(scope, "RetStmt");
15671567
1568 try irb.setCursorAtEndAndAppendBlock(err_block);1568 try irb.setCursorAtEndAndAppendBlock(err_block);
1569 if (have_err_defers) {1569 if (have_err_defers) {
...@@ -2528,7 +2528,7 @@ pub async fn gen(...@@ -2528,7 +2528,7 @@ pub async fn gen(
2528 var irb = try Builder.init(comp, tree_scope, scope);2528 var irb = try Builder.init(comp, tree_scope, scope);
2529 errdefer irb.abort();2529 errdefer irb.abort();
25302530
2531 const entry_block = try irb.createBasicBlock(scope, c"Entry");2531 const entry_block = try irb.createBasicBlock(scope, "Entry");
2532 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.2532 entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
2533 try irb.setCursorAtEndAndAppendBlock(entry_block);2533 try irb.setCursorAtEndAndAppendBlock(entry_block);
25342534
src-self-hosted/link.zig+63-63
...@@ -55,7 +55,7 @@ pub async fn link(comp: *Compilation) !void {...@@ -55,7 +55,7 @@ pub async fn link(comp: *Compilation) !void {
5555
56 // even though we're calling LLD as a library it thinks the first56 // even though we're calling LLD as a library it thinks the first
57 // argument is its own exe name57 // argument is its own exe name
58 try ctx.args.append(c"lld");58 try ctx.args.append("lld");
5959
60 if (comp.haveLibC()) {60 if (comp.haveLibC()) {
61 ctx.libc = ctx.comp.override_libc orelse blk: {61 ctx.libc = ctx.comp.override_libc orelse blk: {
...@@ -145,7 +145,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -145,7 +145,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
145 // lj->args.append("-T");145 // lj->args.append("-T");
146 // lj->args.append(g->linker_script);146 // lj->args.append(g->linker_script);
147 //}147 //}
148 try ctx.args.append(c"--gc-sections");148 try ctx.args.append("--gc-sections");
149149
150 //lj->args.append("-m");150 //lj->args.append("-m");
151 //lj->args.append(getLDMOption(&g->zig_target));151 //lj->args.append(getLDMOption(&g->zig_target));
...@@ -155,9 +155,9 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -155,9 +155,9 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
155 //Buf *soname = nullptr;155 //Buf *soname = nullptr;
156 if (ctx.comp.is_static) {156 if (ctx.comp.is_static) {
157 if (util.isArmOrThumb(ctx.comp.target)) {157 if (util.isArmOrThumb(ctx.comp.target)) {
158 try ctx.args.append(c"-Bstatic");158 try ctx.args.append("-Bstatic");
159 } else {159 } else {
160 try ctx.args.append(c"-static");160 try ctx.args.append("-static");
161 }161 }
162 }162 }
163 //} else if (shared) {163 //} else if (shared) {
...@@ -170,7 +170,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -170,7 +170,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
170 // soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);170 // soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
171 //}171 //}
172172
173 try ctx.args.append(c"-o");173 try ctx.args.append("-o");
174 try ctx.args.append(ctx.out_file_path.ptr());174 try ctx.args.append(ctx.out_file_path.ptr());
175175
176 if (ctx.link_in_crt) {176 if (ctx.link_in_crt) {
...@@ -213,10 +213,10 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -213,10 +213,10 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
213 //}213 //}
214214
215 if (ctx.comp.haveLibC()) {215 if (ctx.comp.haveLibC()) {
216 try ctx.args.append(c"-L");216 try ctx.args.append("-L");
217 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);217 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");
220 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);220 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
221221
222 if (!ctx.comp.is_static) {222 if (!ctx.comp.is_static) {
...@@ -225,7 +225,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -225,7 +225,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
225 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;225 if (util.getDynamicLinkerPath(ctx.comp.target)) |dl| break :blk dl;
226 return error.LibCMissingDynamicLinker;226 return error.LibCMissingDynamicLinker;
227 };227 };
228 try ctx.args.append(c"-dynamic-linker");228 try ctx.args.append("-dynamic-linker");
229 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);229 try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
230 }230 }
231 }231 }
...@@ -272,23 +272,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -272,23 +272,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
272 // libc dep272 // libc dep
273 if (ctx.comp.haveLibC()) {273 if (ctx.comp.haveLibC()) {
274 if (ctx.comp.is_static) {274 if (ctx.comp.is_static) {
275 try ctx.args.append(c"--start-group");275 try ctx.args.append("--start-group");
276 try ctx.args.append(c"-lgcc");276 try ctx.args.append("-lgcc");
277 try ctx.args.append(c"-lgcc_eh");277 try ctx.args.append("-lgcc_eh");
278 try ctx.args.append(c"-lc");278 try ctx.args.append("-lc");
279 try ctx.args.append(c"-lm");279 try ctx.args.append("-lm");
280 try ctx.args.append(c"--end-group");280 try ctx.args.append("--end-group");
281 } else {281 } else {
282 try ctx.args.append(c"-lgcc");282 try ctx.args.append("-lgcc");
283 try ctx.args.append(c"--as-needed");283 try ctx.args.append("--as-needed");
284 try ctx.args.append(c"-lgcc_s");284 try ctx.args.append("-lgcc_s");
285 try ctx.args.append(c"--no-as-needed");285 try ctx.args.append("--no-as-needed");
286 try ctx.args.append(c"-lc");286 try ctx.args.append("-lc");
287 try ctx.args.append(c"-lm");287 try ctx.args.append("-lm");
288 try ctx.args.append(c"-lgcc");288 try ctx.args.append("-lgcc");
289 try ctx.args.append(c"--as-needed");289 try ctx.args.append("--as-needed");
290 try ctx.args.append(c"-lgcc_s");290 try ctx.args.append("-lgcc_s");
291 try ctx.args.append(c"--no-as-needed");291 try ctx.args.append("--no-as-needed");
292 }292 }
293 }293 }
294294
...@@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void {...@@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
299 }299 }
300300
301 if (ctx.comp.target != Target.Native) {301 if (ctx.comp.target != Target.Native) {
302 try ctx.args.append(c"--allow-shlib-undefined");302 try ctx.args.append("--allow-shlib-undefined");
303 }303 }
304304
305 if (ctx.comp.target.getOs() == .zen) {305 if (ctx.comp.target.getOs() == .zen) {
306 try ctx.args.append(c"-e");306 try ctx.args.append("-e");
307 try ctx.args.append(c"_start");307 try ctx.args.append("_start");
308308
309 try ctx.args.append(c"--image-base=0x10000000");309 try ctx.args.append("--image-base=0x10000000");
310 }310 }
311}311}
312312
...@@ -317,23 +317,23 @@ fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {...@@ -317,23 +317,23 @@ fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
317}317}
318318
319fn constructLinkerArgsCoff(ctx: *Context) !void {319fn constructLinkerArgsCoff(ctx: *Context) !void {
320 try ctx.args.append(c"-NOLOGO");320 try ctx.args.append("-NOLOGO");
321321
322 if (!ctx.comp.strip) {322 if (!ctx.comp.strip) {
323 try ctx.args.append(c"-DEBUG");323 try ctx.args.append("-DEBUG");
324 }324 }
325325
326 switch (ctx.comp.target.getArch()) {326 switch (ctx.comp.target.getArch()) {
327 .i386 => try ctx.args.append(c"-MACHINE:X86"),327 .i386 => try ctx.args.append("-MACHINE:X86"),
328 .x86_64 => try ctx.args.append(c"-MACHINE:X64"),328 .x86_64 => try ctx.args.append("-MACHINE:X64"),
329 .aarch64 => try ctx.args.append(c"-MACHINE:ARM"),329 .aarch64 => try ctx.args.append("-MACHINE:ARM"),
330 else => return error.UnsupportedLinkArchitecture,330 else => return error.UnsupportedLinkArchitecture,
331 }331 }
332332
333 if (ctx.comp.windows_subsystem_windows) {333 if (ctx.comp.windows_subsystem_windows) {
334 try ctx.args.append(c"/SUBSYSTEM:windows");334 try ctx.args.append("/SUBSYSTEM:windows");
335 } else if (ctx.comp.windows_subsystem_console) {335 } else if (ctx.comp.windows_subsystem_console) {
336 try ctx.args.append(c"/SUBSYSTEM:console");336 try ctx.args.append("/SUBSYSTEM:console");
337 }337 }
338338
339 const is_library = ctx.comp.kind == .Lib;339 const is_library = ctx.comp.kind == .Lib;
...@@ -367,14 +367,14 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -367,14 +367,14 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
367367
368 // Visual C++ 2015 Conformance Changes368 // Visual C++ 2015 Conformance Changes
369 // https://msdn.microsoft.com/en-us/library/bb531344.aspx369 // 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
372 // msvcrt depends on kernel32372 // msvcrt depends on kernel32
373 try ctx.args.append(c"kernel32.lib");373 try ctx.args.append("kernel32.lib");
374 } else {374 } else {
375 try ctx.args.append(c"-NODEFAULTLIB");375 try ctx.args.append("-NODEFAULTLIB");
376 if (!is_library) {376 if (!is_library) {
377 try ctx.args.append(c"-ENTRY:WinMainCRTStartup");377 try ctx.args.append("-ENTRY:WinMainCRTStartup");
378 // TODO378 // TODO
379 //if (g->have_winmain) {379 //if (g->have_winmain) {
380 // lj->args.append("-ENTRY:WinMain");380 // lj->args.append("-ENTRY:WinMain");
...@@ -385,7 +385,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -385,7 +385,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
385 }385 }
386386
387 if (is_library and !ctx.comp.is_static) {387 if (is_library and !ctx.comp.is_static) {
388 try ctx.args.append(c"-DLL");388 try ctx.args.append("-DLL");
389 }389 }
390390
391 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {391 //for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
...@@ -463,18 +463,18 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {...@@ -463,18 +463,18 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
463}463}
464464
465fn constructLinkerArgsMachO(ctx: *Context) !void {465fn constructLinkerArgsMachO(ctx: *Context) !void {
466 try ctx.args.append(c"-demangle");466 try ctx.args.append("-demangle");
467467
468 if (ctx.comp.linker_rdynamic) {468 if (ctx.comp.linker_rdynamic) {
469 try ctx.args.append(c"-export_dynamic");469 try ctx.args.append("-export_dynamic");
470 }470 }
471471
472 const is_lib = ctx.comp.kind == .Lib;472 const is_lib = ctx.comp.kind == .Lib;
473 const shared = !ctx.comp.is_static and is_lib;473 const shared = !ctx.comp.is_static and is_lib;
474 if (ctx.comp.is_static) {474 if (ctx.comp.is_static) {
475 try ctx.args.append(c"-static");475 try ctx.args.append("-static");
476 } else {476 } else {
477 try ctx.args.append(c"-dynamic");477 try ctx.args.append("-dynamic");
478 }478 }
479479
480 //if (is_lib) {480 //if (is_lib) {
...@@ -503,7 +503,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -503,7 +503,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
503 // }503 // }
504 //}504 //}
505505
506 try ctx.args.append(c"-arch");506 try ctx.args.append("-arch");
507 const darwin_arch_str = try std.cstr.addNullByte(507 const darwin_arch_str = try std.cstr.addNullByte(
508 &ctx.arena.allocator,508 &ctx.arena.allocator,
509 ctx.comp.target.getDarwinArchString(),509 ctx.comp.target.getDarwinArchString(),
...@@ -512,22 +512,22 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -512,22 +512,22 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
512512
513 const platform = try DarwinPlatform.get(ctx.comp);513 const platform = try DarwinPlatform.get(ctx.comp);
514 switch (platform.kind) {514 switch (platform.kind) {
515 .MacOS => try ctx.args.append(c"-macosx_version_min"),515 .MacOS => try ctx.args.append("-macosx_version_min"),
516 .IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),516 .IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
517 .IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),517 .IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
518 }518 }
519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);519 const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
520 try ctx.args.append(ver_str.ptr);520 try ctx.args.append(ver_str.ptr);
521521
522 if (ctx.comp.kind == .Exe) {522 if (ctx.comp.kind == .Exe) {
523 if (ctx.comp.is_static) {523 if (ctx.comp.is_static) {
524 try ctx.args.append(c"-no_pie");524 try ctx.args.append("-no_pie");
525 } else {525 } else {
526 try ctx.args.append(c"-pie");526 try ctx.args.append("-pie");
527 }527 }
528 }528 }
529529
530 try ctx.args.append(c"-o");530 try ctx.args.append("-o");
531 try ctx.args.append(ctx.out_file_path.ptr());531 try ctx.args.append(ctx.out_file_path.ptr());
532532
533 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {533 //for (size_t i = 0; i < g->rpath_list.length; i += 1) {
...@@ -537,27 +537,27 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -537,27 +537,27 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
537 //add_rpath(lj, &lj->out_file);537 //add_rpath(lj, &lj->out_file);
538538
539 if (shared) {539 if (shared) {
540 try ctx.args.append(c"-headerpad_max_install_names");540 try ctx.args.append("-headerpad_max_install_names");
541 } else if (ctx.comp.is_static) {541 } else if (ctx.comp.is_static) {
542 try ctx.args.append(c"-lcrt0.o");542 try ctx.args.append("-lcrt0.o");
543 } else {543 } else {
544 switch (platform.kind) {544 switch (platform.kind) {
545 .MacOS => {545 .MacOS => {
546 if (platform.versionLessThan(10, 5)) {546 if (platform.versionLessThan(10, 5)) {
547 try ctx.args.append(c"-lcrt1.o");547 try ctx.args.append("-lcrt1.o");
548 } else if (platform.versionLessThan(10, 6)) {548 } 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");
550 } else if (platform.versionLessThan(10, 8)) {550 } 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");
552 }552 }
553 },553 },
554 .IPhoneOS => {554 .IPhoneOS => {
555 if (ctx.comp.target.getArch() == .aarch64) {555 if (ctx.comp.target.getArch() == .aarch64) {
556 // iOS does not need any crt1 files for arm64556 // iOS does not need any crt1 files for arm64
557 } else if (platform.versionLessThan(3, 1)) {557 } else if (platform.versionLessThan(3, 1)) {
558 try ctx.args.append(c"-lcrt1.o");558 try ctx.args.append("-lcrt1.o");
559 } else if (platform.versionLessThan(6, 0)) {559 } 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");
561 }561 }
562 },562 },
563 .IPhoneOSSimulator => {}, // no crt1.o needed563 .IPhoneOSSimulator => {}, // no crt1.o needed
...@@ -589,7 +589,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -589,7 +589,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
589 // to make syscalls because the syscall numbers are not documented589 // to make syscalls because the syscall numbers are not documented
590 // and change between versions.590 // and change between versions.
591 // so we always link against libSystem591 // so we always link against libSystem
592 try ctx.args.append(c"-lSystem");592 try ctx.args.append("-lSystem");
593 } else {593 } else {
594 if (mem.indexOfScalar(u8, lib.name, '/') == null) {594 if (mem.indexOfScalar(u8, lib.name, '/') == null) {
595 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);595 const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
...@@ -601,15 +601,15 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {...@@ -601,15 +601,15 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
601 }601 }
602 }602 }
603 } else {603 } else {
604 try ctx.args.append(c"-undefined");604 try ctx.args.append("-undefined");
605 try ctx.args.append(c"dynamic_lookup");605 try ctx.args.append("dynamic_lookup");
606 }606 }
607607
608 if (platform.kind == .MacOS) {608 if (platform.kind == .MacOS) {
609 if (platform.versionLessThan(10, 5)) {609 if (platform.versionLessThan(10, 5)) {
610 try ctx.args.append(c"-lgcc_s.10.4");610 try ctx.args.append("-lgcc_s.10.4");
611 } else if (platform.versionLessThan(10, 6)) {611 } 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");
613 }613 }
614 } else {614 } else {
615 @panic("TODO");615 @panic("TODO");
src-self-hosted/llvm.zig+22-22
...@@ -83,16 +83,16 @@ pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;...@@ -83,16 +83,16 @@ pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
83pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;83pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
8484
85pub const AddGlobal = LLVMAddGlobal;85pub 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
88pub const ConstStringInContext = LLVMConstStringInContext;88pub 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
91pub const ConstInt = LLVMConstInt;91pub const ConstInt = LLVMConstInt;
92extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;92extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
9393
94pub const BuildLoad = LLVMBuildLoad;94pub 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
97pub const ConstNull = LLVMConstNull;97pub const ConstNull = LLVMConstNull;
98extern fn LLVMConstNull(Ty: *Type) ?*Value;98extern fn LLVMConstNull(Ty: *Type) ?*Value;
...@@ -110,24 +110,24 @@ pub const CreateEnumAttribute = LLVMCreateEnumAttribute;...@@ -110,24 +110,24 @@ pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
110extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;110extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
111111
112pub const AddFunction = LLVMAddFunction;112pub 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
115pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;115pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
116extern fn ZigLLVMCreateCompileUnit(116extern fn ZigLLVMCreateCompileUnit(
117 dibuilder: *DIBuilder,117 dibuilder: *DIBuilder,
118 lang: c_uint,118 lang: c_uint,
119 difile: *DIFile,119 difile: *DIFile,
120 producer: [*]const u8,120 producer: [*:0]const u8,
121 is_optimized: bool,121 is_optimized: bool,
122 flags: [*]const u8,122 flags: [*:0]const u8,
123 runtime_version: c_uint,123 runtime_version: c_uint,
124 split_name: [*]const u8,124 split_name: [*:0]const u8,
125 dwo_id: u64,125 dwo_id: u64,
126 emit_debug_info: bool,126 emit_debug_info: bool,
127) ?*DICompileUnit;127) ?*DICompileUnit;
128128
129pub const CreateFile = ZigLLVMCreateFile;129pub 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
132pub const ArrayType = LLVMArrayType;132pub const ArrayType = LLVMArrayType;
133extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;133extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
...@@ -145,7 +145,7 @@ pub const IntTypeInContext = LLVMIntTypeInContext;...@@ -145,7 +145,7 @@ pub const IntTypeInContext = LLVMIntTypeInContext;
145extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;145extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
146146
147pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;147pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
148extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;148extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *Context) ?*Module;
149149
150pub const VoidTypeInContext = LLVMVoidTypeInContext;150pub const VoidTypeInContext = LLVMVoidTypeInContext;
151extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;151extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
...@@ -157,7 +157,7 @@ pub const ContextDispose = LLVMContextDispose;...@@ -157,7 +157,7 @@ pub const ContextDispose = LLVMContextDispose;
157extern fn LLVMContextDispose(C: *Context) void;157extern fn LLVMContextDispose(C: *Context) void;
158158
159pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;159pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
160extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;160extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*:0]u8;
161161
162pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;162pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
163extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;163extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
...@@ -165,9 +165,9 @@ extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;...@@ -165,9 +165,9 @@ extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
165pub const CreateTargetMachine = ZigLLVMCreateTargetMachine;165pub const CreateTargetMachine = ZigLLVMCreateTargetMachine;
166extern fn ZigLLVMCreateTargetMachine(166extern fn ZigLLVMCreateTargetMachine(
167 T: *Target,167 T: *Target,
168 Triple: [*]const u8,168 Triple: [*:0]const u8,
169 CPU: [*]const u8,169 CPU: [*:0]const u8,
170 Features: [*]const u8,170 Features: [*:0]const u8,
171 Level: CodeGenOptLevel,171 Level: CodeGenOptLevel,
172 Reloc: RelocMode,172 Reloc: RelocMode,
173 CodeModel: CodeModel,173 CodeModel: CodeModel,
...@@ -175,10 +175,10 @@ extern fn ZigLLVMCreateTargetMachine(...@@ -175,10 +175,10 @@ extern fn ZigLLVMCreateTargetMachine(
175) ?*TargetMachine;175) ?*TargetMachine;
176176
177pub const GetHostCPUName = LLVMGetHostCPUName;177pub const GetHostCPUName = LLVMGetHostCPUName;
178extern fn LLVMGetHostCPUName() ?[*]u8;178extern fn LLVMGetHostCPUName() ?[*:0]u8;
179179
180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;180pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
181extern fn ZigLLVMGetNativeFeatures() ?[*]u8;181extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8;
182182
183pub const GetElementType = LLVMGetElementType;183pub const GetElementType = LLVMGetElementType;
184extern fn LLVMGetElementType(Ty: *Type) *Type;184extern fn LLVMGetElementType(Ty: *Type) *Type;
...@@ -190,16 +190,16 @@ pub const BuildStore = LLVMBuildStore;...@@ -190,16 +190,16 @@ pub const BuildStore = LLVMBuildStore;
190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;190extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
191191
192pub const BuildAlloca = LLVMBuildAlloca;192pub 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
195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;195pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;196pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
197197
198pub const GetTargetFromTriple = LLVMGetTargetFromTriple;198pub 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
201pub const VerifyModule = LLVMVerifyModule;201pub 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
204pub const GetInsertBlock = LLVMGetInsertBlock;204pub const GetInsertBlock = LLVMGetInsertBlock;
205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;205extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
...@@ -216,7 +216,7 @@ pub const GetParam = LLVMGetParam;...@@ -216,7 +216,7 @@ pub const GetParam = LLVMGetParam;
216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;216extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
217217
218pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;218pub 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
221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;221pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;222extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
...@@ -278,14 +278,14 @@ pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;...@@ -278,14 +278,14 @@ pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
278extern fn ZigLLVMTargetMachineEmitToFile(278extern fn ZigLLVMTargetMachineEmitToFile(
279 targ_machine_ref: *TargetMachine,279 targ_machine_ref: *TargetMachine,
280 module_ref: *Module,280 module_ref: *Module,
281 filename: [*]const u8,281 filename: [*:0]const u8,
282 output_type: EmitOutputType,282 output_type: EmitOutputType,
283 error_message: *[*]u8,283 error_message: *[*:0]u8,
284 is_debug: bool,284 is_debug: bool,
285 is_small: bool,285 is_small: bool,
286) bool;286) bool;
287287
288pub const BuildCall = ZigLLVMBuildCall;288pub 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
291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;291pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
src-self-hosted/stage1.zig+3-3
...@@ -27,7 +27,7 @@ comptime {...@@ -27,7 +27,7 @@ comptime {
27// ABI warning27// ABI warning
28export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {28export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
29 const info_zen = @import("main.zig").info_zen;29 const info_zen = @import("main.zig").info_zen;
30 ptr.* = &info_zen;30 ptr.* = info_zen;
31 len.* = info_zen.len;31 len.* = info_zen.len;
32}32}
3333
...@@ -144,7 +144,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {...@@ -144,7 +144,7 @@ export fn stage2_render_ast(tree: *ast.Tree, output_file: *FILE) Error {
144144
145// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,145// TODO: just use the actual self-hosted zig fmt. Until https://github.com/ziglang/zig/issues/2377,
146// we use a blocking implementation.146// 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 {
148 if (std.debug.runtime_safety) {148 if (std.debug.runtime_safety) {
149 fmtMain(argc, argv) catch unreachable;149 fmtMain(argc, argv) catch unreachable;
150 } else {150 } else {
...@@ -156,7 +156,7 @@ export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {...@@ -156,7 +156,7 @@ export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int {
156 return 0;156 return 0;
157}157}
158158
159fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void {159fn fmtMain(argc: c_int, argv: [*]const [*:0]const u8) !void {
160 const allocator = std.heap.c_allocator;160 const allocator = std.heap.c_allocator;
161 var args_list = std.ArrayList([]const u8).init(allocator);161 var args_list = std.ArrayList([]const u8).init(allocator);
162 const argc_usize = @intCast(usize, argc);162 const argc_usize = @intCast(usize, argc);
src-self-hosted/translate_c.zig+24-13
...@@ -113,7 +113,7 @@ const Context = struct {...@@ -113,7 +113,7 @@ const Context = struct {
113 }113 }
114114
115 /// Convert a null-terminated C string to a slice allocated in the arena115 /// 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 {
117 return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));117 return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));
118 }118 }
119119
...@@ -696,10 +696,9 @@ fn transStringLiteral(...@@ -696,10 +696,9 @@ fn transStringLiteral(
696 len = 0;696 len = 0;
697 for (str) |c| len += escapeChar(c, &char_buf).len;697 for (str) |c| len += escapeChar(c, &char_buf).len;
698698
699 const buf = try rp.c.a().alloc(u8, len + "c\"\"".len);699 const buf = try rp.c.a().alloc(u8, len + "\"\"".len);
700 buf[0] = 'c';700 buf[0] = '"';
701 buf[1] = '"';701 writeEscapedString(buf[1..], str);
702 writeEscapedString(buf[2..], str);
703 buf[buf.len - 1] = '"';702 buf[buf.len - 1] = '"';
704703
705 const token = try appendToken(rp.c, .StringLiteral, buf);704 const token = try appendToken(rp.c, .StringLiteral, buf);
...@@ -1104,16 +1103,30 @@ fn transCreateNodePtrType(...@@ -1104,16 +1103,30 @@ fn transCreateNodePtrType(
1104 is_const: bool,1103 is_const: bool,
1105 is_volatile: bool,1104 is_volatile: bool,
1106 op_tok_id: std.zig.Token.Id,1105 op_tok_id: std.zig.Token.Id,
1107 bytes: []const u8,
1108) !*ast.Node.PrefixOp {1106) !*ast.Node.PrefixOp {
1109 const node = try c.a().create(ast.Node.PrefixOp);1107 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 };
1110 node.* = ast.Node.PrefixOp{1125 node.* = ast.Node.PrefixOp{
1111 .base = ast.Node{ .id = .PrefixOp },1126 .base = ast.Node{ .id = .PrefixOp },
1112 .op_token = try appendToken(c, op_tok_id, bytes),1127 .op_token = op_token,
1113 .op = ast.Node.PrefixOp.Op{1128 .op = ast.Node.PrefixOp.Op{
1114 .PtrType = ast.Node.PrefixOp.PtrInfo{1129 .PtrType = .{
1115 .allowzero_token = null,
1116 .align_info = null,
1117 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,1130 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
1118 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,1131 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
1119 },1132 },
...@@ -1224,7 +1237,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -1224,7 +1237,6 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
1224 ZigClangQualType_isConstQualified(child_qt),1237 ZigClangQualType_isConstQualified(child_qt),
1225 ZigClangQualType_isVolatileQualified(child_qt),1238 ZigClangQualType_isVolatileQualified(child_qt),
1226 .Asterisk,1239 .Asterisk,
1227 "*",
1228 );1240 );
1229 optional_node.rhs = &pointer_node.base;1241 optional_node.rhs = &pointer_node.base;
1230 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);1242 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
...@@ -1234,8 +1246,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour...@@ -1234,8 +1246,7 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
1234 rp.c,1246 rp.c,
1235 ZigClangQualType_isConstQualified(child_qt),1247 ZigClangQualType_isConstQualified(child_qt),
1236 ZigClangQualType_isVolatileQualified(child_qt),1248 ZigClangQualType_isVolatileQualified(child_qt),
1237 .BracketStarCBracket,1249 .Identifier,
1238 "[*c]",
1239 );1250 );
1240 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);1251 pointer_node.rhs = try transQualType(rp, child_qt, source_loc);
1241 return &pointer_node.base;1252 return &pointer_node.base;
src-self-hosted/util.zig+3-3
...@@ -172,9 +172,9 @@ pub fn getDarwinArchString(self: Target) []const u8 {...@@ -172,9 +172,9 @@ pub fn getDarwinArchString(self: Target) []const u8 {
172172
173pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {173pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
174 var result: *llvm.Target = undefined;174 var result: *llvm.Target = undefined;
175 var err_msg: [*]u8 = undefined;175 var err_msg: [*:0]u8 = undefined;
176 if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {176 if (llvm.GetTargetFromTriple(triple.toSlice(), &result, &err_msg) != 0) {
177 std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);177 std.debug.warn("triple: {s} error: {s}\n", triple.toSlice(), err_msg);
178 return error.UnsupportedTarget;178 return error.UnsupportedTarget;
179 }179 }
180 return result;180 return result;
src-self-hosted/value.zig+1-1
...@@ -473,7 +473,7 @@ pub const Value = struct {...@@ -473,7 +473,7 @@ pub const Value = struct {
473 dont_null_terminate,473 dont_null_terminate,
474 ) orelse return error.OutOfMemory;474 ) orelse return error.OutOfMemory;
475 const str_init_type = llvm.TypeOf(llvm_str_init);475 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;
477 llvm.SetInitializer(global, llvm_str_init);477 llvm.SetInitializer(global, llvm_str_init);
478 llvm.SetLinkage(global, llvm.PrivateLinkage);478 llvm.SetLinkage(global, llvm.PrivateLinkage);
479 llvm.SetGlobalConstant(global, 1);479 llvm.SetGlobalConstant(global, 1);
src/all_types.hpp+25-4
...@@ -101,6 +101,10 @@ struct IrExecutable {...@@ -101,6 +101,10 @@ struct IrExecutable {
101 bool is_inline;101 bool is_inline;
102 bool is_generic_instantiation;102 bool is_generic_instantiation;
103 bool need_err_code_spill;103 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();
104};108};
105109
106enum OutType {110enum OutType {
...@@ -236,9 +240,6 @@ struct ConstPtrValue {...@@ -236,9 +240,6 @@ struct ConstPtrValue {
236 struct {240 struct {
237 ConstExprValue *array_val;241 ConstExprValue *array_val;
238 size_t elem_index;242 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;
242 } base_array;243 } base_array;
243 struct {244 struct {
244 ConstExprValue *struct_val;245 ConstExprValue *struct_val;
...@@ -351,6 +352,7 @@ struct LazyValueSliceType {...@@ -351,6 +352,7 @@ struct LazyValueSliceType {
351 LazyValue base;352 LazyValue base;
352353
353 IrAnalyze *ira;354 IrAnalyze *ira;
355 IrInstruction *sentinel; // can be null
354 IrInstruction *elem_type;356 IrInstruction *elem_type;
355 IrInstruction *align_inst; // can be null357 IrInstruction *align_inst; // can be null
356358
...@@ -363,6 +365,7 @@ struct LazyValuePtrType {...@@ -363,6 +365,7 @@ struct LazyValuePtrType {
363 LazyValue base;365 LazyValue base;
364366
365 IrAnalyze *ira;367 IrAnalyze *ira;
368 IrInstruction *sentinel; // can be null
366 IrInstruction *elem_type;369 IrInstruction *elem_type;
367 IrInstruction *align_inst; // can be null370 IrInstruction *align_inst; // can be null
368371
...@@ -598,6 +601,7 @@ enum NodeType {...@@ -598,6 +601,7 @@ enum NodeType {
598 NodeTypeSuspend,601 NodeTypeSuspend,
599 NodeTypeAnyFrameType,602 NodeTypeAnyFrameType,
600 NodeTypeEnumLiteral,603 NodeTypeEnumLiteral,
604 NodeTypeVarFieldType,
601};605};
602606
603enum CallingConvention {607enum CallingConvention {
...@@ -818,6 +822,7 @@ struct AstNodePrefixOpExpr {...@@ -818,6 +822,7 @@ struct AstNodePrefixOpExpr {
818822
819struct AstNodePointerType {823struct AstNodePointerType {
820 Token *star_token;824 Token *star_token;
825 AstNode *sentinel;
821 AstNode *align_expr;826 AstNode *align_expr;
822 BigInt *bit_offset_start;827 BigInt *bit_offset_start;
823 BigInt *host_int_bytes;828 BigInt *host_int_bytes;
...@@ -828,11 +833,13 @@ struct AstNodePointerType {...@@ -828,11 +833,13 @@ struct AstNodePointerType {
828};833};
829834
830struct AstNodeInferredArrayType {835struct AstNodeInferredArrayType {
836 AstNode *sentinel; // can be null
831 AstNode *child_type;837 AstNode *child_type;
832};838};
833839
834struct AstNodeArrayType {840struct AstNodeArrayType {
835 AstNode *size;841 AstNode *size;
842 AstNode *sentinel;
836 AstNode *child_type;843 AstNode *child_type;
837 AstNode *align_expr;844 AstNode *align_expr;
838 Token *allow_zero_token;845 Token *allow_zero_token;
...@@ -997,7 +1004,6 @@ struct AstNodeStructField {...@@ -997,7 +1004,6 @@ struct AstNodeStructField {
9971004
998struct AstNodeStringLiteral {1005struct AstNodeStringLiteral {
999 Buf *buf;1006 Buf *buf;
1000 bool c;
1001};1007};
10021008
1003struct AstNodeCharLiteral {1009struct AstNodeCharLiteral {
...@@ -1204,6 +1210,11 @@ struct ZigTypePointer {...@@ -1204,6 +1210,11 @@ struct ZigTypePointer {
1204 // struct.1210 // struct.
1205 InferredStructField *inferred_struct_field;1211 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
1207 PtrLen ptr_len;1218 PtrLen ptr_len;
1208 uint32_t explicit_alignment; // 0 means use ABI alignment1219 uint32_t explicit_alignment; // 0 means use ABI alignment
12091220
...@@ -1231,6 +1242,7 @@ struct ZigTypeFloat {...@@ -1231,6 +1242,7 @@ struct ZigTypeFloat {
1231struct ZigTypeArray {1242struct ZigTypeArray {
1232 ZigType *child_type;1243 ZigType *child_type;
1233 uint64_t len;1244 uint64_t len;
1245 ConstExprValue *sentinel;
1234};1246};
12351247
1236struct TypeStructField {1248struct TypeStructField {
...@@ -1756,8 +1768,10 @@ struct TypeId {...@@ -1756,8 +1768,10 @@ struct TypeId {
17561768
1757 union {1769 union {
1758 struct {1770 struct {
1771 CodeGen *codegen;
1759 ZigType *child_type;1772 ZigType *child_type;
1760 InferredStructField *inferred_struct_field;1773 InferredStructField *inferred_struct_field;
1774 ConstExprValue *sentinel;
1761 PtrLen ptr_len;1775 PtrLen ptr_len;
1762 uint32_t alignment;1776 uint32_t alignment;
17631777
...@@ -1770,8 +1784,10 @@ struct TypeId {...@@ -1770,8 +1784,10 @@ struct TypeId {
1770 bool allow_zero;1784 bool allow_zero;
1771 } pointer;1785 } pointer;
1772 struct {1786 struct {
1787 CodeGen *codegen;
1773 ZigType *child_type;1788 ZigType *child_type;
1774 uint64_t size;1789 uint64_t size;
1790 ConstExprValue *sentinel;
1775 } array;1791 } array;
1776 struct {1792 struct {
1777 bool is_signed;1793 bool is_signed;
...@@ -1950,6 +1966,7 @@ struct CodeGen {...@@ -1950,6 +1966,7 @@ struct CodeGen {
1950 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;1966 HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
1951 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;1967 HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
1952 HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;1968 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
1954 ZigList<Tld *> resolve_queue;1971 ZigList<Tld *> resolve_queue;
1955 size_t resolve_queue_index;1972 size_t resolve_queue_index;
...@@ -2026,6 +2043,7 @@ struct CodeGen {...@@ -2026,6 +2043,7 @@ struct CodeGen {
2026 IrInstruction *invalid_instruction;2043 IrInstruction *invalid_instruction;
2027 IrInstruction *unreach_instruction;2044 IrInstruction *unreach_instruction;
20282045
2046 ConstExprValue const_zero_byte;
2029 ConstExprValue const_void_val;2047 ConstExprValue const_void_val;
2030 ConstExprValue panic_msg_vals[PanicMsgIdCount];2048 ConstExprValue panic_msg_vals[PanicMsgIdCount];
20312049
...@@ -2982,12 +3000,14 @@ struct IrInstructionArrayType {...@@ -2982,12 +3000,14 @@ struct IrInstructionArrayType {
2982 IrInstruction base;3000 IrInstruction base;
29833001
2984 IrInstruction *size;3002 IrInstruction *size;
3003 IrInstruction *sentinel;
2985 IrInstruction *child_type;3004 IrInstruction *child_type;
2986};3005};
29873006
2988struct IrInstructionPtrType {3007struct IrInstructionPtrType {
2989 IrInstruction base;3008 IrInstruction base;
29903009
3010 IrInstruction *sentinel;
2991 IrInstruction *align_value;3011 IrInstruction *align_value;
2992 IrInstruction *child_type;3012 IrInstruction *child_type;
2993 uint32_t bit_offset_start;3013 uint32_t bit_offset_start;
...@@ -3007,6 +3027,7 @@ struct IrInstructionAnyFrameType {...@@ -3007,6 +3027,7 @@ struct IrInstructionAnyFrameType {
3007struct IrInstructionSliceType {3027struct IrInstructionSliceType {
3008 IrInstruction base;3028 IrInstruction base;
30093029
3030 IrInstruction *sentinel;
3010 IrInstruction *align_value;3031 IrInstruction *align_value;
3011 IrInstruction *child_type;3032 IrInstruction *child_type;
3012 bool is_const;3033 bool is_const;
src/analyze.cpp+199-156
...@@ -452,18 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {...@@ -452,18 +452,6 @@ ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type) {
452 return entry;452 return entry;
453}453}
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
467ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {455ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
468 if (fn->frame_type != nullptr) {456 if (fn->frame_type != nullptr) {
469 return fn->frame_type;457 return fn->frame_type;
...@@ -483,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {...@@ -483,10 +471,47 @@ ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) {
483 return entry;471 return entry;
484}472}
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
486ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,511ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const,
487 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,512 bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
488 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero,513 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)
490{515{
491 assert(ptr_len != PtrLenC || allow_zero);516 assert(ptr_len != PtrLenC || allow_zero);
492 assert(!type_is_invalid(child_type));517 assert(!type_is_invalid(child_type));
...@@ -509,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -509,9 +534,11 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
509 TypeId type_id = {};534 TypeId type_id = {};
510 ZigType **parent_pointer = nullptr;535 ZigType **parent_pointer = nullptr;
511 if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||536 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)
513 {539 {
514 type_id.id = ZigTypeIdPointer;540 type_id.id = ZigTypeIdPointer;
541 type_id.data.pointer.codegen = g;
515 type_id.data.pointer.child_type = child_type;542 type_id.data.pointer.child_type = child_type;
516 type_id.data.pointer.is_const = is_const;543 type_id.data.pointer.is_const = is_const;
517 type_id.data.pointer.is_volatile = is_volatile;544 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...@@ -522,6 +549,7 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
522 type_id.data.pointer.allow_zero = allow_zero;549 type_id.data.pointer.allow_zero = allow_zero;
523 type_id.data.pointer.vector_index = vector_index;550 type_id.data.pointer.vector_index = vector_index;
524 type_id.data.pointer.inferred_struct_field = inferred_struct_field;551 type_id.data.pointer.inferred_struct_field = inferred_struct_field;
552 type_id.data.pointer.sentinel = sentinel;
525553
526 auto existing_entry = g->type_table.maybe_get(type_id);554 auto existing_entry = g->type_table.maybe_get(type_id);
527 if (existing_entry)555 if (existing_entry)
...@@ -537,56 +565,35 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -537,56 +565,35 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
537565
538 ZigType *entry = new_type_table_entry(ZigTypeIdPointer);566 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 }
550 buf_resize(&entry->name, 0);568 buf_resize(&entry->name, 0);
551 if (host_int_bytes == 0 && byte_alignment == 0 && vector_index == VECTOR_INDEX_NONE) {569 if (inferred_struct_field != nullptr) {
552 if (inferred_struct_field == nullptr) {570 buf_appendf(&entry->name, "(");
553 buf_appendf(&entry->name, "%s%s%s%s%s",571 }
554 star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));572 switch (ptr_len) {
555 } else {573 case PtrLenSingle:
556 buf_appendf(&entry->name, "(%s%s%s%s field '%s' of %s)",574 buf_appendf(&entry->name, "*");
557 star_str, const_str, volatile_str, allow_zero_str,575 break;
558 buf_ptr(inferred_struct_field->field_name),576 case PtrLenUnknown:
559 buf_ptr(&inferred_struct_field->inferred_struct_type->name));577 buf_appendf(&entry->name, "[*");
560 }578 break;
561 } else if (host_int_bytes == 0 && vector_index == VECTOR_INDEX_NONE) {579 case PtrLenC:
562 buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,580 assert(sentinel == nullptr);
563 const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));581 buf_appendf(&entry->name, "[*c]");
564 } else if (byte_alignment == 0) {582 break;
565 assert(vector_index == VECTOR_INDEX_NONE);583 }
566 buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s",584 if (sentinel != nullptr) {
567 star_str,585 buf_appendf(&entry->name, ":");
568 bit_offset_in_host, host_int_bytes,586 render_const_value(g, &entry->name, sentinel);
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));
589 }587 }
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
591 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {598 if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
592 if (type_has_bits(child_type)) {599 if (type_has_bits(child_type)) {
...@@ -615,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con...@@ -615,6 +622,9 @@ ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_con
615 entry->data.pointer.allow_zero = allow_zero;622 entry->data.pointer.allow_zero = allow_zero;
616 entry->data.pointer.vector_index = vector_index;623 entry->data.pointer.vector_index = vector_index;
617 entry->data.pointer.inferred_struct_field = inferred_struct_field;624 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
619 if (parent_pointer) {629 if (parent_pointer) {
620 *parent_pointer = entry;630 *parent_pointer = entry;
...@@ -629,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons...@@ -629,12 +639,12 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
629 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)639 uint32_t bit_offset_in_host, uint32_t host_int_bytes, bool allow_zero)
630{640{
631 return get_pointer_to_type_extra2(g, child_type, is_const, is_volatile, ptr_len,641 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);
633}643}
634644
635ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {645ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) {
636 return get_pointer_to_type_extra2(g, child_type, is_const, false, PtrLenSingle, 0, 0, 0, false,646 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);
638}648}
639649
640ZigType *get_optional_type(CodeGen *g, ZigType *child_type) {650ZigType *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...@@ -750,11 +760,13 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
750 return entry;760 return entry;
751}761}
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) {
754 TypeId type_id = {};764 TypeId type_id = {};
755 type_id.id = ZigTypeIdArray;765 type_id.id = ZigTypeIdArray;
766 type_id.data.array.codegen = g;
756 type_id.data.array.child_type = child_type;767 type_id.data.array.child_type = child_type;
757 type_id.data.array.size = array_size;768 type_id.data.array.size = array_size;
769 type_id.data.array.sentinel = sentinel;
758 auto existing_entry = g->type_table.maybe_get(type_id);770 auto existing_entry = g->type_table.maybe_get(type_id);
759 if (existing_entry) {771 if (existing_entry) {
760 return existing_entry->value;772 return existing_entry->value;
...@@ -765,14 +777,27 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {...@@ -765,14 +777,27 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) {
765 ZigType *entry = new_type_table_entry(ZigTypeIdArray);777 ZigType *entry = new_type_table_entry(ZigTypeIdArray);
766778
767 buf_resize(&entry->name, 0);779 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;
771 entry->abi_align = child_type->abi_align;795 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
774 entry->data.array.child_type = child_type;798 entry->data.array.child_type = child_type;
775 entry->data.array.len = array_size;799 entry->data.array.len = array_size;
800 entry->data.array.sentinel = sentinel;
776801
777 g->type_table.put(type_id, entry);802 g->type_table.put(type_id, entry);
778 return entry;803 return entry;
...@@ -789,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -789,10 +814,14 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
789814
790 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);815 ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
791816
792 // replace the & with [] to go from a ptr type name to a slice type name
793 buf_resize(&entry->name, 0);817 buf_resize(&entry->name, 0);
794 size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3;818 buf_appendf(&entry->name, "[");
795 buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset);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
797 unsigned element_count = 2;826 unsigned element_count = 2;
798 Buf *ptr_field_name = buf_create_from_str("ptr");827 Buf *ptr_field_name = buf_create_from_str("ptr");
...@@ -832,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {...@@ -832,22 +861,6 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
832 entry->data.structure.fields[slice_len_index]->gen_index = 0;861 entry->data.structure.fields[slice_len_index]->gen_index = 0;
833 }862 }
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
851 if (type_has_bits(ptr_type)) {864 if (type_has_bits(ptr_type)) {
852 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;865 entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits;
853 entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size;866 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 *...@@ -1150,6 +1163,10 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *
1150Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {1163Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
1151 if (type_val->special != ConstValSpecialLazy) {1164 if (type_val->special != ConstValSpecialLazy) {
1152 assert(type_val->special == ConstValSpecialStatic);1165 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 }
1153 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);1170 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
1154 return ErrorNone;1171 return ErrorNone;
1155 }1172 }
...@@ -3638,6 +3655,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {...@@ -3638,6 +3655,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
3638 case NodeTypeEnumLiteral:3655 case NodeTypeEnumLiteral:
3639 case NodeTypeAnyFrameType:3656 case NodeTypeAnyFrameType:
3640 case NodeTypeErrorSetField:3657 case NodeTypeErrorSetField:
3658 case NodeTypeVarFieldType:
3641 zig_unreachable();3659 zig_unreachable();
3642 }3660 }
3643}3661}
...@@ -5041,7 +5059,6 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {...@@ -5041,7 +5059,6 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
5041 hash_val += (uint32_t)1764906839;5059 hash_val += (uint32_t)1764906839;
5042 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);5060 hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
5043 hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);5061 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;
5045 return hash_val;5062 return hash_val;
5046 case ConstPtrSpecialBaseStruct:5063 case ConstPtrSpecialBaseStruct:
5047 hash_val += (uint32_t)3518317043;5064 hash_val += (uint32_t)3518317043;
...@@ -5545,8 +5562,23 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {...@@ -5545,8 +5562,23 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
5545 zig_unreachable();5562 zig_unreachable();
5546}5563}
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
5548ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {5577ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
5549 Error err;5578 Error err;
5579 if (ty == g->builtin_types.entry_var) {
5580 return ReqCompTimeYes;
5581 }
5550 switch (ty->id) {5582 switch (ty->id) {
5551 case ZigTypeIdInvalid:5583 case ZigTypeIdInvalid:
5552 zig_unreachable();5584 zig_unreachable();
...@@ -5612,52 +5644,26 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {...@@ -5612,52 +5644,26 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
5612 return;5644 return;
5613 }5645 }
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) {
5630 // first we build the underlying array5647 // first we build the underlying array
5631 size_t len_with_null = buf_len(str) + 1;
5632 ConstExprValue *array_val = create_const_vals(1);5648 ConstExprValue *array_val = create_const_vals(1);
5633 array_val->special = ConstValSpecialStatic;5649 array_val->special = ConstValSpecialStatic;
5634 array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null);5650 array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), &g->const_zero_byte);
5635 // TODO buf optimization5651 array_val->data.x_array.special = ConstArraySpecialBuf;
5636 array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);5652 array_val->data.x_array.data.s_buf = str;
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);
56475653
5648 // then make the pointer point to it5654 // then make the pointer point to it
5649 const_val->special = ConstValSpecialStatic;5655 const_val->special = ConstValSpecialStatic;
5650 // TODO make this `[*]null u8` instead of `[*]u8`5656 const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
5651 const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,5657 PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, nullptr);
5652 PtrLenUnknown, 0, 0, 0, false);5658 const_val->data.x_ptr.special = ConstPtrSpecialRef;
5653 const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;5659 const_val->data.x_ptr.data.ref.pointee = array_val;
5654 const_val->data.x_ptr.data.base_array.array_val = array_val;5660
5655 const_val->data.x_ptr.data.base_array.elem_index = 0;5661 g->string_literals_table.put(str, const_val);
5656 const_val->data.x_ptr.data.base_array.is_cstr = true;
5657}5662}
5658ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {5663
5664ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
5659 ConstExprValue *const_val = create_const_vals(1);5665 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);
5661 return const_val;5667 return const_val;
5662}5668}
56635669
...@@ -5707,6 +5713,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {...@@ -5707,6 +5713,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {
5707 return const_val;5713 return const_val;
5708}5714}
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
5710void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {5728void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {
5711 const_val->special = ConstValSpecialStatic;5729 const_val->special = ConstValSpecialStatic;
5712 const_val->type = type;5730 const_val->type = type;
...@@ -6069,7 +6087,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {...@@ -6069,7 +6087,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
60696087
6070 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6088 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6071 fields.append({"@instruction_addresses",6089 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});
6073 }6091 }
60746092
6075 frame_type->data.frame.locals_struct = get_struct_type(g, buf_ptr(&frame_type->name),6093 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) {...@@ -6277,7 +6295,7 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
6277 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {6295 if (codegen_fn_has_err_ret_tracing_stack(g, fn, true)) {
6278 fields.append({"@stack_trace", get_stack_trace_type(g), 0});6296 fields.append({"@stack_trace", get_stack_trace_type(g), 0});
6279 fields.append({"@instruction_addresses",6297 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});
6281 }6299 }
62826300
6283 for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {6301 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) {...@@ -6441,8 +6459,6 @@ bool ir_get_var_is_comptime(ZigVar *var) {
6441bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {6459bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
6442 if (a->data.x_ptr.special != b->data.x_ptr.special)6460 if (a->data.x_ptr.special != b->data.x_ptr.special)
6443 return false;6461 return false;
6444 if (a->data.x_ptr.mut != b->data.x_ptr.mut)
6445 return false;
6446 switch (a->data.x_ptr.special) {6462 switch (a->data.x_ptr.special) {
6447 case ConstPtrSpecialInvalid:6463 case ConstPtrSpecialInvalid:
6448 zig_unreachable();6464 zig_unreachable();
...@@ -6459,8 +6475,6 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {...@@ -6459,8 +6475,6 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
6459 }6475 }
6460 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)6476 if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
6461 return false;6477 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;
6464 return true;6478 return true;
6465 case ConstPtrSpecialBaseStruct:6479 case ConstPtrSpecialBaseStruct:
6466 if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val &&6480 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...@@ -6536,9 +6550,19 @@ static bool const_values_equal_array(CodeGen *g, ConstExprValue *a, ConstExprVal
6536}6550}
65376551
6538bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {6552bool 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;
6540 assert(a->special == ConstValSpecialStatic);6554 assert(a->special == ConstValSpecialStatic);
6541 assert(b->special == ConstValSpecialStatic);6555 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 }
6542 switch (a->type->id) {6566 switch (a->type->id) {
6543 case ZigTypeIdOpaque:6567 case ZigTypeIdOpaque:
6544 zig_unreachable();6568 zig_unreachable();
...@@ -6704,15 +6728,10 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val...@@ -6704,15 +6728,10 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val
6704 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));6728 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
6705 return;6729 return;
6706 case ConstPtrSpecialBaseArray:6730 case ConstPtrSpecialBaseArray:
6707 if (const_val->data.x_ptr.data.base_array.is_cstr) {6731 buf_appendf(buf, "*");
6708 buf_appendf(buf, "*(c str lit)");6732 // TODO we need a source node for const_ptr_pointee because it can generate compile errors
6709 return;6733 render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
6710 } else {6734 return;
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 }
6716 case ConstPtrSpecialHardCodedAddr:6735 case ConstPtrSpecialHardCodedAddr:
6717 buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),6736 buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
6718 const_val->data.x_ptr.data.hard_coded_addr.addr);6737 const_val->data.x_ptr.data.hard_coded_addr.addr);
...@@ -7032,17 +7051,19 @@ uint32_t type_id_hash(TypeId x) {...@@ -7032,17 +7051,19 @@ uint32_t type_id_hash(TypeId x) {
7032 return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);7051 return hash_ptr(x.data.error_union.err_set_type) ^ hash_ptr(x.data.error_union.payload_type);
7033 case ZigTypeIdPointer:7052 case ZigTypeIdPointer:
7034 return hash_ptr(x.data.pointer.child_type) +7053 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 +
7036 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +7055 (x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
7037 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +7056 (x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
7038 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +7057 (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
7039 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +7058 (((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
7040 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +7059 (((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
7041 (((uint32_t)x.data.pointer.vector_index) ^ (uint32_t)0x19199716) +7060 (((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);
7043 case ZigTypeIdArray:7063 case ZigTypeIdArray:
7044 return hash_ptr(x.data.array.child_type) +7064 return hash_ptr(x.data.array.child_type) *
7045 ((uint32_t)x.data.array.size ^ (uint32_t)2122979968);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);
7046 case ZigTypeIdInt:7067 case ZigTypeIdInt:
7047 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +7068 return (x.data.integer.is_signed ? (uint32_t)2652528194 : (uint32_t)163929201) +
7048 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);7069 (((uint32_t)x.data.integer.bit_count) ^ (uint32_t)2998081557);
...@@ -7093,6 +7114,11 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -7093,6 +7114,11 @@ bool type_id_eql(TypeId a, TypeId b) {
7093 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&7114 a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
7094 a.data.pointer.vector_index == b.data.pointer.vector_index &&7115 a.data.pointer.vector_index == b.data.pointer.vector_index &&
7095 a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes &&7116 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 ) &&
7096 (7122 (
7097 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||7123 a.data.pointer.inferred_struct_field == b.data.pointer.inferred_struct_field ||
7098 (a.data.pointer.inferred_struct_field != nullptr &&7124 (a.data.pointer.inferred_struct_field != nullptr &&
...@@ -7104,7 +7130,12 @@ bool type_id_eql(TypeId a, TypeId b) {...@@ -7104,7 +7130,12 @@ bool type_id_eql(TypeId a, TypeId b) {
7104 );7130 );
7105 case ZigTypeIdArray:7131 case ZigTypeIdArray:
7106 return a.data.array.child_type == b.data.array.child_type &&7132 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 );
7108 case ZigTypeIdInt:7139 case ZigTypeIdInt:
7109 return a.data.integer.is_signed == b.data.integer.is_signed &&7140 return a.data.integer.is_signed == b.data.integer.is_signed &&
7110 a.data.integer.bit_count == b.data.integer.bit_count;7141 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...@@ -7761,7 +7792,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
77617792
7762 bool done = false;7793 bool done = false;
7763 if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||7794 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)
7765 {7797 {
7766 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,7798 ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
7767 PtrLenUnknown, 0, 0, 0, false);7799 PtrLenUnknown, 0, 0, 0, false);
...@@ -7780,7 +7812,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa...@@ -7780,7 +7812,8 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
7780 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;7812 ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index]->type_entry;
7781 assert(child_ptr_type->id == ZigTypeIdPointer);7813 assert(child_ptr_type->id == ZigTypeIdPointer);
7782 if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||7814 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)
7784 {7817 {
7785 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;7818 ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
7786 ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,7819 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...@@ -8290,7 +8323,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8290 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;8323 size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->type_entry->abi_size;
8291 if (padding_bytes > 0) {8324 if (padding_bytes > 0) {
8292 ZigType *u8_type = get_int_type(g, false, 8);8325 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);
8294 LLVMTypeRef union_element_types[] = {8327 LLVMTypeRef union_element_types[] = {
8295 most_aligned_union_member->type_entry->llvm_type,8328 most_aligned_union_member->type_entry->llvm_type,
8296 get_llvm_type(g, padding_array),8329 get_llvm_type(g, padding_array),
...@@ -8324,7 +8357,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -8324,7 +8357,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
8324 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);8357 union_type_ref = get_llvm_type(g, most_aligned_union_member->type_entry);
8325 } else {8358 } else {
8326 ZigType *u8_type = get_int_type(g, false, 8);8359 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);
8328 LLVMTypeRef union_element_types[] = {8361 LLVMTypeRef union_element_types[] = {
8329 get_llvm_type(g, most_aligned_union_member->type_entry),8362 get_llvm_type(g, most_aligned_union_member->type_entry),
8330 get_llvm_type(g, padding_array),8363 get_llvm_type(g, padding_array),
...@@ -8405,19 +8438,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus...@@ -8405,19 +8438,19 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus
8405 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||8438 if (type->data.pointer.is_const || type->data.pointer.is_volatile ||
8406 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||8439 type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle ||
8407 type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero ||8440 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)
8409 {8442 {
8410 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));8443 assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl));
8411 ZigType *peer_type;8444 ZigType *peer_type;
8412 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {8445 if (type->data.pointer.vector_index == VECTOR_INDEX_NONE) {
8413 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,8446 peer_type = get_pointer_to_type_extra2(g, elem_type, false, false,
8414 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,8447 PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false,
8415 VECTOR_INDEX_NONE, nullptr);8448 VECTOR_INDEX_NONE, nullptr, nullptr);
8416 } else {8449 } else {
8417 uint32_t host_vec_len = type->data.pointer.host_int_bytes;8450 uint32_t host_vec_len = type->data.pointer.host_int_bytes;
8418 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);8451 ZigType *host_vec_type = get_vector_type(g, host_vec_len, elem_type);
8419 peer_type = get_pointer_to_type_extra2(g, host_vec_type, false, false,8452 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);
8421 }8454 }
8422 type->llvm_type = get_llvm_type(g, peer_type);8455 type->llvm_type = get_llvm_type(g, peer_type);
8423 type->llvm_di_type = get_llvm_di_type(g, peer_type);8456 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) {...@@ -8646,14 +8679,16 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
86468679
8647 ZigType *elem_type = type->data.array.child_type;8680 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;
8649 // TODO https://github.com/ziglang/zig/issues/14248684 // 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
8652 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);8687 uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
8653 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);8688 uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
86548689
8655 type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,8690 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);
8657}8692}
86588693
8659static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {8694static 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,...@@ -9143,3 +9178,11 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
9143 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);9178 *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
9144 return ErrorNone;9179 return ErrorNone;
9145}9180}
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,...@@ -24,7 +24,8 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type,
24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,24ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type,
25 bool is_const, bool is_volatile, PtrLen ptr_len,25 bool is_const, bool is_volatile, PtrLen ptr_len,
26 uint32_t byte_alignment, uint32_t bit_offset, uint32_t unaligned_bit_count,26 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);
28uint64_t type_size(CodeGen *g, ZigType *type_entry);29uint64_t type_size(CodeGen *g, ZigType *type_entry);
29uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);30uint64_t type_size_bits(CodeGen *g, ZigType *type_entry);
30ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits);31ZigType *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);...@@ -33,7 +34,7 @@ ZigType **get_c_int_type_ptr(CodeGen *g, CIntType c_int_type);
33ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);34ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type);
34ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);35ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id);
35ZigType *get_optional_type(CodeGen *g, ZigType *child_type);36ZigType *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);
37ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);38ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type);
38ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,39ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind,
39 AstNode *decl_node, const char *full_name, Buf *bare_name, ContainerLayout layout);40 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);...@@ -126,9 +127,6 @@ ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
126void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);127void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
127ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);128ConstExprValue *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
132void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);130void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
133ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);131ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);
134132
...@@ -176,6 +174,9 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t...@@ -176,6 +174,9 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
176void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);174void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
177ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);175ConstExprValue *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
179ConstExprValue *create_const_vals(size_t count);180ConstExprValue *create_const_vals(size_t count);
180ConstExprValue **alloc_const_vals_ptrs(size_t count);181ConstExprValue **alloc_const_vals_ptrs(size_t count);
181ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count);182ConstExprValue **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,...@@ -275,5 +276,5 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,
275 ZigType *var_type, const char *name_hint);276 ZigType *var_type, const char *name_hint);
276Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,277Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
277 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);278 ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
278279ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
279#endif280#endif
src/ast_render.cpp+8-5
...@@ -147,9 +147,9 @@ static const char *token_to_ptr_len_str(Token *tok) {...@@ -147,9 +147,9 @@ static const char *token_to_ptr_len_str(Token *tok) {
147 case TokenIdStar:147 case TokenIdStar:
148 case TokenIdStarStar:148 case TokenIdStarStar:
149 return "*";149 return "*";
150 case TokenIdBracketStarBracket:150 case TokenIdLBracket:
151 return "[*]";151 return "[*]";
152 case TokenIdBracketStarCBracket:152 case TokenIdSymbol:
153 return "[*c]";153 return "[*c]";
154 default:154 default:
155 zig_unreachable();155 zig_unreachable();
...@@ -268,6 +268,8 @@ static const char *node_type_str(NodeType node_type) {...@@ -268,6 +268,8 @@ static const char *node_type_str(NodeType node_type) {
268 return "EnumLiteral";268 return "EnumLiteral";
269 case NodeTypeErrorSetField:269 case NodeTypeErrorSetField:
270 return "ErrorSetField";270 return "ErrorSetField";
271 case NodeTypeVarFieldType:
272 return "VarFieldType";
271 }273 }
272 zig_unreachable();274 zig_unreachable();
273}275}
...@@ -619,9 +621,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -619,9 +621,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
619 break;621 break;
620 case NodeTypeStringLiteral:622 case NodeTypeStringLiteral:
621 {623 {
622 if (node->data.string_literal.c) {
623 fprintf(ar->f, "c");
624 }
625 Buf tmp_buf = BUF_INIT;624 Buf tmp_buf = BUF_INIT;
626 string_literal_escape(node->data.string_literal.buf, &tmp_buf);625 string_literal_escape(node->data.string_literal.buf, &tmp_buf);
627 fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));626 fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));
...@@ -1187,6 +1186,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {...@@ -1187,6 +1186,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
1187 fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));1186 fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
1188 break;1187 break;
1189 }1188 }
1189 case NodeTypeVarFieldType: {
1190 fprintf(ar->f, "var");
1191 break;
1192 }
1190 case NodeTypeParamDecl:1193 case NodeTypeParamDecl:
1191 case NodeTypeTestDecl:1194 case NodeTypeTestDecl:
1192 case NodeTypeStructField:1195 case NodeTypeStructField:
src/codegen.cpp+48-27
...@@ -949,7 +949,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {...@@ -949,7 +949,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
949 if (!val->global_refs->llvm_global) {949 if (!val->global_refs->llvm_global) {
950950
951 Buf *buf_msg = panic_msg_buf(msg_id);951 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;
953 init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);953 init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);
954954
955 render_const_val(g, val, "");955 render_const_val(g, val, "");
...@@ -2784,14 +2784,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,...@@ -2784,14 +2784,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2784 IrInstruction *op1 = bin_op_instruction->op1;2784 IrInstruction *op1 = bin_op_instruction->op1;
2785 IrInstruction *op2 = bin_op_instruction->op2;2785 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 );
2795 ZigType *operand_type = op1->value.type;2787 ZigType *operand_type = op1->value.type;
2796 ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;2788 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,...@@ -2848,7 +2840,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
2848 AddSubMulMul;2840 AddSubMulMul;
28492841
2850 if (scalar_type->id == ZigTypeIdPointer) {2842 if (scalar_type->id == ZigTypeIdPointer) {
2851 assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
2852 LLVMValueRef subscript_value;2843 LLVMValueRef subscript_value;
2853 if (operand_type->id == ZigTypeIdVector)2844 if (operand_type->id == ZigTypeIdVector)
2854 zig_panic("TODO: Implement vector operations on pointers.");2845 zig_panic("TODO: Implement vector operations on pointers.");
...@@ -3077,7 +3068,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -3077,7 +3068,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
3077 case CastOpNumLitToConcrete:3068 case CastOpNumLitToConcrete:
3078 zig_unreachable();3069 zig_unreachable();
3079 case CastOpNoop:3070 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 }
3081 case CastOpIntToFloat:3079 case CastOpIntToFloat:
3082 assert(actual_type->id == ZigTypeIdInt);3080 assert(actual_type->id == ZigTypeIdInt);
3083 if (actual_type->data.integral.is_signed) {3081 if (actual_type->data.integral.is_signed) {
...@@ -3709,8 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3709,8 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3709 array_type = array_type->data.pointer.child_type;3707 array_type = array_type->data.pointer.child_type;
3710 }3708 }
3711 if (safety_check_on) {3709 if (safety_check_on) {
3712 LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,3710 uint64_t extra_len_from_sentinel = (array_type->data.array.sentinel != nullptr) ? 1 : 0;
3713 array_type->data.array.len, false);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);
3714 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);3713 add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
3715 }3714 }
3716 if (array_ptr_type->data.pointer.host_int_bytes != 0) {3715 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...@@ -3753,7 +3752,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3753 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);3752 LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type);
3754 assert(array_type->data.structure.is_slice);3753 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;
3757 if (!type_has_bits(ptr_type)) {3756 if (!type_has_bits(ptr_type)) {
3758 if (safety_check_on) {3757 if (safety_check_on) {
3759 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);3758 assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind);
...@@ -3770,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3770,7 +3769,8 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
3770 assert(len_index != SIZE_MAX);3769 assert(len_index != SIZE_MAX);
3771 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");3770 LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, "");
3772 LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, "");3771 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);
3774 }3774 }
37753775
3776 size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index;3776 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...@@ -6637,11 +6637,20 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
6637 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;6637 ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
6638 assert(array_const_val->type->id == ZigTypeIdArray);6638 assert(array_const_val->type->id == ZigTypeIdArray);
6639 if (!type_has_bits(array_const_val->type)) {6639 if (!type_has_bits(array_const_val->type)) {
6640 // make this a null pointer6640 if (array_const_val->type->data.array.sentinel != nullptr) {
6641 ZigType *usize = g->builtin_types.entry_usize;6641 ConstExprValue *pointee = array_const_val->type->data.array.sentinel;
6642 const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),6642 render_const_val(g, pointee, "");
6643 get_llvm_type(g, const_val->type));6643 render_const_val_global(g, pointee, "");
6644 return const_val->global_refs->llvm_value;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 }
6645 }6654 }
6646 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;6655 size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
6647 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);6656 LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
...@@ -6955,7 +6964,9 @@ check: switch (const_val->special) {...@@ -6955,7 +6964,9 @@ check: switch (const_val->special) {
6955 case ConstArraySpecialUndef:6964 case ConstArraySpecialUndef:
6956 return LLVMGetUndef(get_llvm_type(g, type_entry));6965 return LLVMGetUndef(get_llvm_type(g, type_entry));
6957 case ConstArraySpecialNone: {6966 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);
6959 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);6970 LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
6960 bool make_unnamed_struct = false;6971 bool make_unnamed_struct = false;
6961 for (uint64_t i = 0; i < len; i += 1) {6972 for (uint64_t i = 0; i < len; i += 1) {
...@@ -6964,15 +6975,19 @@ check: switch (const_val->special) {...@@ -6964,15 +6975,19 @@ check: switch (const_val->special) {
6964 values[i] = val;6975 values[i] = val;
6965 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);6976 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
6966 }6977 }
6978 if (type_entry->data.array.sentinel != nullptr) {
6979 values[len] = gen_const_val(g, type_entry->data.array.sentinel, "");
6980 }
6967 if (make_unnamed_struct) {6981 if (make_unnamed_struct) {
6968 return LLVMConstStruct(values, len, true);6982 return LLVMConstStruct(values, full_len, true);
6969 } else {6983 } else {
6970 return LLVMConstArray(element_type_ref, values, (unsigned)len);6984 return LLVMConstArray(element_type_ref, values, (unsigned)full_len);
6971 }6985 }
6972 }6986 }
6973 case ConstArraySpecialBuf: {6987 case ConstArraySpecialBuf: {
6974 Buf *buf = const_val->data.x_array.data.s_buf;6988 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);
6976 }6991 }
6977 }6992 }
6978 zig_unreachable();6993 zig_unreachable();
...@@ -7465,7 +7480,7 @@ static void do_code_gen(CodeGen *g) {...@@ -7465,7 +7480,7 @@ static void do_code_gen(CodeGen *g) {
7465 !is_async && !have_err_ret_trace_arg;7480 !is_async && !have_err_ret_trace_arg;
7466 LLVMValueRef err_ret_array_val = nullptr;7481 LLVMValueRef err_ret_array_val = nullptr;
7467 if (have_err_ret_trace_stack) {7482 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);
7469 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));7484 err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type));
74707485
7471 (void)get_llvm_type(g, get_stack_trace_type(g));7486 (void)get_llvm_type(g, get_stack_trace_type(g));
...@@ -8628,6 +8643,11 @@ static void init(CodeGen *g) {...@@ -8628,6 +8643,11 @@ static void init(CodeGen *g) {
8628 g->const_void_val.type = g->builtin_types.entry_void;8643 g->const_void_val.type = g->builtin_types.entry_void;
8629 g->const_void_val.global_refs = allocate<ConstGlobalRefs>(1);8644 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
8631 {8651 {
8632 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);8652 ConstGlobalRefs *global_refs = allocate<ConstGlobalRefs>(PanicMsgIdCount);
8633 for (size_t i = 0; i < PanicMsgIdCount; i += 1) {8653 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) {...@@ -9067,7 +9087,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
9067 zig_unreachable();9087 zig_unreachable();
90689088
9069 ConstExprValue *test_fn_array = create_const_vals(1);9089 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);
9071 test_fn_array->special = ConstValSpecialStatic;9091 test_fn_array->special = ConstValSpecialStatic;
9072 test_fn_array->data.x_array.data.s_none.elements = create_const_vals(g->test_fns.length);9092 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) {...@@ -9092,7 +9112,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
9092 this_val->data.x_struct.fields = alloc_const_vals_ptrs(2);9112 this_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
90939113
9094 ConstExprValue *name_field = this_val->data.x_struct.fields[0];9114 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;
9096 init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true);9116 init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true);
90979117
9098 ConstExprValue *fn_field = this_val->data.x_struct.fields[1];9118 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...@@ -10415,6 +10435,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
10415 g->external_prototypes.init(8);10435 g->external_prototypes.init(8);
10416 g->string_literals_table.init(16);10436 g->string_literals_table.init(16);
10417 g->type_info_cache.init(32);10437 g->type_info_cache.init(32);
10438 g->one_possible_values.init(32);
10418 g->is_test_build = is_test_build;10439 g->is_test_build = is_test_build;
10419 g->is_single_threaded = false;10440 g->is_single_threaded = false;
10420 buf_resize(&g->global_asm, 0);10441 buf_resize(&g->global_asm, 0);
src/ir.cpp+843-253
...@@ -66,6 +66,11 @@ enum ConstCastResultId {...@@ -66,6 +66,11 @@ enum ConstCastResultId {
66 ConstCastResultIdUnresolvedInferredErrSet,66 ConstCastResultIdUnresolvedInferredErrSet,
67 ConstCastResultIdAsyncAllocatorType,67 ConstCastResultIdAsyncAllocatorType,
68 ConstCastResultIdBadAllowsZero,68 ConstCastResultIdBadAllowsZero,
69 ConstCastResultIdArrayChild,
70 ConstCastResultIdSentinelArrays,
71 ConstCastResultIdPtrLens,
72 ConstCastResultIdCV,
73 ConstCastResultIdPtrSentinel,
69};74};
7075
71struct ConstCastOnly;76struct ConstCastOnly;
...@@ -87,7 +92,11 @@ struct ConstCastErrUnionErrSetMismatch;...@@ -87,7 +92,11 @@ struct ConstCastErrUnionErrSetMismatch;
87struct ConstCastErrUnionPayloadMismatch;92struct ConstCastErrUnionPayloadMismatch;
88struct ConstCastErrSetMismatch;93struct ConstCastErrSetMismatch;
89struct ConstCastTypeMismatch;94struct ConstCastTypeMismatch;
95struct ConstCastArrayMismatch;
90struct ConstCastBadAllowsZero;96struct ConstCastBadAllowsZero;
97struct ConstCastBadNullTermArrays;
98struct ConstCastBadCV;
99struct ConstCastPtrSentinel;
91100
92struct ConstCastOnly {101struct ConstCastOnly {
93 ConstCastResultId id;102 ConstCastResultId id;
...@@ -99,11 +108,15 @@ struct ConstCastOnly {...@@ -99,11 +108,15 @@ struct ConstCastOnly {
99 ConstCastErrUnionPayloadMismatch *error_union_payload;108 ConstCastErrUnionPayloadMismatch *error_union_payload;
100 ConstCastErrUnionErrSetMismatch *error_union_error_set;109 ConstCastErrUnionErrSetMismatch *error_union_error_set;
101 ConstCastTypeMismatch *type_mismatch;110 ConstCastTypeMismatch *type_mismatch;
111 ConstCastArrayMismatch *array_mismatch;
102 ConstCastOnly *return_type;112 ConstCastOnly *return_type;
103 ConstCastOnly *null_wrap_ptr_child;113 ConstCastOnly *null_wrap_ptr_child;
104 ConstCastArg fn_arg;114 ConstCastArg fn_arg;
105 ConstCastArgNoAlias arg_no_alias;115 ConstCastArgNoAlias arg_no_alias;
106 ConstCastBadAllowsZero *bad_allows_zero;116 ConstCastBadAllowsZero *bad_allows_zero;
117 ConstCastBadNullTermArrays *sentinel_arrays;
118 ConstCastBadCV *bad_cv;
119 ConstCastPtrSentinel *bad_ptr_sentinel;
107 } data;120 } data;
108};121};
109122
...@@ -130,6 +143,12 @@ struct ConstCastSliceMismatch {...@@ -130,6 +143,12 @@ struct ConstCastSliceMismatch {
130 ZigType *actual_child;143 ZigType *actual_child;
131};144};
132145
146struct ConstCastArrayMismatch {
147 ConstCastOnly child;
148 ZigType *wanted_child;
149 ZigType *actual_child;
150};
151
133struct ConstCastErrUnionErrSetMismatch {152struct ConstCastErrUnionErrSetMismatch {
134 ConstCastOnly child;153 ConstCastOnly child;
135 ZigType *wanted_err_set;154 ZigType *wanted_err_set;
...@@ -151,11 +170,28 @@ struct ConstCastBadAllowsZero {...@@ -151,11 +170,28 @@ struct ConstCastBadAllowsZero {
151 ZigType *actual_type;170 ZigType *actual_type;
152};171};
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
155static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);189static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
156static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,190static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
157 ResultLoc *result_loc);191 ResultLoc *result_loc);
158static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type);192static 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);
159static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,195static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,
160 ResultLoc *result_loc);196 ResultLoc *result_loc);
161static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg);197static 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...@@ -217,10 +253,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
217 case OnePossibleValueInvalid:253 case OnePossibleValueInvalid:
218 zig_unreachable();254 zig_unreachable();
219 case OnePossibleValueYes:255 case OnePossibleValueYes:
220 result = create_const_vals(1);256 return get_the_one_possible_value(g, const_val->type->data.pointer.child_type);
221 result->type = const_val->type->data.pointer.child_type;
222 result->special = ConstValSpecialStatic;
223 return result;
224 case OnePossibleValueNo:257 case OnePossibleValueNo:
225 break;258 break;
226 }259 }
...@@ -233,8 +266,12 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c...@@ -233,8 +266,12 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
233 break;266 break;
234 case ConstPtrSpecialBaseArray: {267 case ConstPtrSpecialBaseArray: {
235 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;268 ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
236 expand_undef_array(g, array_val);269 if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
237 result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];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 }
238 break;275 break;
239 }276 }
240 case ConstPtrSpecialBaseStruct: {277 case ConstPtrSpecialBaseStruct: {
...@@ -282,20 +319,20 @@ static bool slice_is_const(ZigType *type) {...@@ -282,20 +319,20 @@ static bool slice_is_const(ZigType *type) {
282319
283// This function returns true when you can change the type of a ConstExprValue and the320// This function returns true when you can change the type of a ConstExprValue and the
284// value remains meaningful.321// value remains meaningful.
285static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {322static bool types_have_same_zig_comptime_repr(CodeGen *codegen, ZigType *expected, ZigType *actual) {
286 if (a == b)323 if (expected == actual)
287 return true;324 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)
290 return true;327 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))
293 return true;330 return true;
294331
295 if (a->id != b->id)332 if (expected->id != actual->id)
296 return false;333 return false;
297334
298 switch (a->id) {335 switch (expected->id) {
299 case ZigTypeIdInvalid:336 case ZigTypeIdInvalid:
300 case ZigTypeIdUnreachable:337 case ZigTypeIdUnreachable:
301 zig_unreachable();338 zig_unreachable();
...@@ -314,12 +351,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -314,12 +351,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
314 case ZigTypeIdAnyFrame:351 case ZigTypeIdAnyFrame:
315 return true;352 return true;
316 case ZigTypeIdFloat:353 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;
318 case ZigTypeIdInt:355 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;
320 case ZigTypeIdStruct:357 case ZigTypeIdStruct:
321 return is_slice(a) && is_slice(b);358 return is_slice(expected) && is_slice(actual);
322 case ZigTypeIdArray:
323 case ZigTypeIdOptional:359 case ZigTypeIdOptional:
324 case ZigTypeIdErrorUnion:360 case ZigTypeIdErrorUnion:
325 case ZigTypeIdEnum:361 case ZigTypeIdEnum:
...@@ -329,6 +365,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {...@@ -329,6 +365,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
329 case ZigTypeIdVector:365 case ZigTypeIdVector:
330 case ZigTypeIdFnFrame:366 case ZigTypeIdFnFrame:
331 return false;367 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)));
332 }373 }
333 zig_unreachable();374 zig_unreachable();
334}375}
...@@ -1299,12 +1340,6 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo...@@ -1299,12 +1340,6 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo
1299 return instruction;1340 return instruction;
1300}1341}
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
1308static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,1343static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
1309 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)1344 IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
1310{1345{
...@@ -1544,9 +1579,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_...@@ -1544,9 +1579,11 @@ static IrInstruction *ir_build_br(IrBuilder *irb, Scope *scope, AstNode *source_
15441579
1545static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1580static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node,
1546 IrInstruction *child_type, bool is_const, bool is_volatile, PtrLen ptr_len,1581 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)
1548{1584{
1549 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);1585 IrInstructionPtrType *ptr_type_of_instruction = ir_build_instruction<IrInstructionPtrType>(irb, scope, source_node);
1586 ptr_type_of_instruction->sentinel = sentinel;
1550 ptr_type_of_instruction->align_value = align_value;1587 ptr_type_of_instruction->align_value = align_value;
1551 ptr_type_of_instruction->child_type = child_type;1588 ptr_type_of_instruction->child_type = child_type;
1552 ptr_type_of_instruction->is_const = is_const;1589 ptr_type_of_instruction->is_const = is_const;
...@@ -1556,6 +1593,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s...@@ -1556,6 +1593,7 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
1556 ptr_type_of_instruction->host_int_bytes = host_int_bytes;1593 ptr_type_of_instruction->host_int_bytes = host_int_bytes;
1557 ptr_type_of_instruction->is_allow_zero = is_allow_zero;1594 ptr_type_of_instruction->is_allow_zero = is_allow_zero;
15581595
1596 if (sentinel) ir_ref_instruction(sentinel, irb->current_basic_block);
1559 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);1597 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
1560 ir_ref_instruction(child_type, irb->current_basic_block);1598 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...@@ -1772,13 +1810,15 @@ static IrInstruction *ir_build_set_float_mode(IrBuilder *irb, Scope *scope, AstN
1772}1810}
17731811
1774static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,1812static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size,
1775 IrInstruction *child_type)1813 IrInstruction *sentinel, IrInstruction *child_type)
1776{1814{
1777 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);1815 IrInstructionArrayType *instruction = ir_build_instruction<IrInstructionArrayType>(irb, scope, source_node);
1778 instruction->size = size;1816 instruction->size = size;
1817 instruction->sentinel = sentinel;
1779 instruction->child_type = child_type;1818 instruction->child_type = child_type;
17801819
1781 ir_ref_instruction(size, irb->current_basic_block);1820 ir_ref_instruction(size, irb->current_basic_block);
1821 if (sentinel != nullptr) ir_ref_instruction(sentinel, irb->current_basic_block);
1782 ir_ref_instruction(child_type, irb->current_basic_block);1822 ir_ref_instruction(child_type, irb->current_basic_block);
17831823
1784 return &instruction->base;1824 return &instruction->base;
...@@ -1794,18 +1834,22 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo...@@ -1794,18 +1834,22 @@ static IrInstruction *ir_build_anyframe_type(IrBuilder *irb, Scope *scope, AstNo
17941834
1795 return &instruction->base;1835 return &instruction->base;
1796}1836}
1837
1797static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node,1838static 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)
1799{1841{
1800 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);1842 IrInstructionSliceType *instruction = ir_build_instruction<IrInstructionSliceType>(irb, scope, source_node);
1801 instruction->is_const = is_const;1843 instruction->is_const = is_const;
1802 instruction->is_volatile = is_volatile;1844 instruction->is_volatile = is_volatile;
1803 instruction->child_type = child_type;1845 instruction->child_type = child_type;
1846 instruction->sentinel = sentinel;
1804 instruction->align_value = align_value;1847 instruction->align_value = align_value;
1805 instruction->is_allow_zero = is_allow_zero;1848 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);
1807 ir_ref_instruction(child_type, irb->current_basic_block);1852 ir_ref_instruction(child_type, irb->current_basic_block);
1808 if (align_value) ir_ref_instruction(align_value, irb->current_basic_block);
18091853
1810 return &instruction->base;1854 return &instruction->base;
1811}1855}
...@@ -6032,9 +6076,9 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {...@@ -6032,9 +6076,9 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {
6032 case TokenIdStar:6076 case TokenIdStar:
6033 case TokenIdStarStar:6077 case TokenIdStarStar:
6034 return PtrLenSingle;6078 return PtrLenSingle;
6035 case TokenIdBracketStarBracket:6079 case TokenIdLBracket:
6036 return PtrLenUnknown;6080 return PtrLenUnknown;
6037 case TokenIdBracketStarCBracket:6081 case TokenIdSymbol:
6038 return PtrLenC;6082 return PtrLenC;
6039 default:6083 default:
6040 zig_unreachable();6084 zig_unreachable();
...@@ -6043,13 +6087,25 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {...@@ -6043,13 +6087,25 @@ static PtrLen star_token_to_ptr_len(TokenId token_id) {
60436087
6044static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {6088static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
6045 assert(node->type == NodeTypePointerType);6089 assert(node->type == NodeTypePointerType);
6090
6046 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);6091 PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
6092
6047 bool is_const = node->data.pointer_type.is_const;6093 bool is_const = node->data.pointer_type.is_const;
6048 bool is_volatile = node->data.pointer_type.is_volatile;6094 bool is_volatile = node->data.pointer_type.is_volatile;
6049 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;6095 bool is_allow_zero = node->data.pointer_type.allow_zero_token != nullptr;
6096 AstNode *sentinel_expr = node->data.pointer_type.sentinel;
6050 AstNode *expr_node = node->data.pointer_type.op_expr;6097 AstNode *expr_node = node->data.pointer_type.op_expr;
6051 AstNode *align_expr = node->data.pointer_type.align_expr;6098 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
6053 IrInstruction *align_value;6109 IrInstruction *align_value;
6054 if (align_expr != nullptr) {6110 if (align_expr != nullptr) {
6055 align_value = ir_gen_node(irb, align_expr, scope);6111 align_value = ir_gen_node(irb, align_expr, scope);
...@@ -6094,7 +6150,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode...@@ -6094,7 +6150,7 @@ static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode
6094 }6150 }
60956151
6096 return ir_build_ptr_type(irb, scope, node, child_type, is_const, is_volatile,6152 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);
6098}6154}
60996155
6100static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node,6156static 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...@@ -6198,13 +6254,22 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
6198 buf_sprintf("initializing array with struct syntax"));6254 buf_sprintf("initializing array with struct syntax"));
6199 return irb->codegen->invalid_instruction;6255 return irb->codegen->invalid_instruction;
6200 }6256 }
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
6201 IrInstruction *elem_type = ir_gen_node(irb,6266 IrInstruction *elem_type = ir_gen_node(irb,
6202 container_init_expr->type->data.inferred_array_type.child_type, scope);6267 container_init_expr->type->data.inferred_array_type.child_type, scope);
6203 if (elem_type == irb->codegen->invalid_instruction)6268 if (elem_type == irb->codegen->invalid_instruction)
6204 return elem_type;6269 return elem_type;
6205 size_t item_count = container_init_expr->entries.length;6270 size_t item_count = container_init_expr->entries.length;
6206 IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);6271 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);
6208 } else {6273 } else {
6209 container_type = ir_gen_node(irb, container_init_expr->type, scope);6274 container_type = ir_gen_node(irb, container_init_expr->type, scope);
6210 if (container_type == irb->codegen->invalid_instruction)6275 if (container_type == irb->codegen->invalid_instruction)
...@@ -6917,11 +6982,7 @@ static IrInstruction *ir_gen_enum_literal(IrBuilder *irb, Scope *scope, AstNode...@@ -6917,11 +6982,7 @@ static IrInstruction *ir_gen_enum_literal(IrBuilder *irb, Scope *scope, AstNode
6917static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) {6982static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
6918 assert(node->type == NodeTypeStringLiteral);6983 assert(node->type == NodeTypeStringLiteral);
69196984
6920 if (node->data.string_literal.c) {6985 return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf);
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 }
6925}6986}
69266987
6927static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *node) {6988static 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...@@ -6932,9 +6993,20 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6932 bool is_const = node->data.array_type.is_const;6993 bool is_const = node->data.array_type.is_const;
6933 bool is_volatile = node->data.array_type.is_volatile;6994 bool is_volatile = node->data.array_type.is_volatile;
6934 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;6995 bool is_allow_zero = node->data.array_type.allow_zero_token != nullptr;
6996 AstNode *sentinel_expr = node->data.array_type.sentinel;
6935 AstNode *align_expr = node->data.array_type.align_expr;6997 AstNode *align_expr = node->data.array_type.align_expr;
69366998
6937 Scope *comptime_scope = create_comptime_scope(irb->codegen, node, scope);6999 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
6938 if (size_node) {7010 if (size_node) {
6939 if (is_const) {7011 if (is_const) {
6940 add_node_error(irb->codegen, node, buf_create_from_str("const qualifier invalid on array type"));7012 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...@@ -6961,7 +7033,7 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6961 if (child_type == irb->codegen->invalid_instruction)7033 if (child_type == irb->codegen->invalid_instruction)
6962 return child_type;7034 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);
6965 } else {7037 } else {
6966 IrInstruction *align_value;7038 IrInstruction *align_value;
6967 if (align_expr != nullptr) {7039 if (align_expr != nullptr) {
...@@ -6976,7 +7048,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n...@@ -6976,7 +7048,8 @@ static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *n
6976 if (child_type == irb->codegen->invalid_instruction)7048 if (child_type == irb->codegen->invalid_instruction)
6977 return child_type;7049 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);
6980 }7053 }
6981}7054}
69827055
...@@ -8486,6 +8559,9 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop...@@ -8486,6 +8559,9 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
8486 add_node_error(irb->codegen, node,8559 add_node_error(irb->codegen, node,
8487 buf_sprintf("inferred array size invalid here"));8560 buf_sprintf("inferred array size invalid here"));
8488 return irb->codegen->invalid_instruction;8561 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);
8489 }8565 }
8490 zig_unreachable();8566 zig_unreachable();
8491}8567}
...@@ -8645,7 +8721,18 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal...@@ -8645,7 +8721,18 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
8645 assert(val != nullptr);8721 assert(val != nullptr);
8646 assert(const_val->type->id == ZigTypeIdPointer);8722 assert(const_val->type->id == ZigTypeIdPointer);
8647 ZigType *expected_type = const_val->type->data.pointer.child_type;8723 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)) {
8649 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))8736 if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
8650 return nullptr;8737 return nullptr;
8651 return const_ptr_pointee_unchecked(codegen, const_val);8738 return const_ptr_pointee_unchecked(codegen, const_val);
...@@ -9793,6 +9880,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9793,6 +9880,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9793 // alignment can be decreased9880 // alignment can be decreased
9794 // bit offset attributes must match exactly9881 // bit offset attributes must match exactly
9795 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one9882 // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
9883 // sentinel-terminated pointers can coerce into PtrLenUnknown
9796 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);9884 ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
9797 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);9885 ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
9798 bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);9886 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...@@ -9804,6 +9892,35 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9804 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&9892 bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
9805 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);9893 (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
9806 if (wanted_opt_or_ptr && actual_opt_or_ptr) {9894 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
9807 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,9924 ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
9808 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);9925 actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
9809 if (child.id == ConstCastResultIdInvalid)9926 if (child.id == ConstCastResultIdInvalid)
...@@ -9842,11 +9959,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted...@@ -9842,11 +9959,7 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9842 result.id = ConstCastResultIdInvalid;9959 result.id = ConstCastResultIdInvalid;
9843 return result;9960 return result;
9844 }9961 }
9845 bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;9962 if (type_has_bits(wanted_type) == type_has_bits(actual_type) &&
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) &&
9850 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&9963 actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
9851 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&9964 actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
9852 get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))9965 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...@@ -9855,6 +9968,36 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
9855 }9968 }
9856 }9969 }
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
9858 // slice const10001 // slice const
9859 if (is_slice(wanted_type) && is_slice(actual_type)) {10002 if (is_slice(wanted_type) && is_slice(actual_type)) {
9860 ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry;10003 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...@@ -10615,6 +10758,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10615 // *[N]T to []T10758 // *[N]T to []T
10616 // *[N]T to E![]T10759 // *[N]T to E![]T
10617 if (cur_type->id == ZigTypeIdPointer &&10760 if (cur_type->id == ZigTypeIdPointer &&
10761 cur_type->data.pointer.ptr_len == PtrLenSingle &&
10618 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&10762 cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
10619 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||10763 ((prev_type->id == ZigTypeIdErrorUnion && is_slice(prev_type->data.error_union.payload_type)) ||
10620 is_slice(prev_type)))10764 is_slice(prev_type)))
...@@ -10623,7 +10767,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10623,7 +10767,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10623 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?10767 ZigType *slice_type = (prev_type->id == ZigTypeIdErrorUnion) ?
10624 prev_type->data.error_union.payload_type : prev_type;10768 prev_type->data.error_union.payload_type : prev_type;
10625 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;10769 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) &&
10627 types_match_const_cast_only(ira,10772 types_match_const_cast_only(ira,
10628 slice_ptr_type->data.pointer.child_type,10773 slice_ptr_type->data.pointer.child_type,
10629 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)10774 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...@@ -10637,6 +10782,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10637 // *[N]T to E![]T10782 // *[N]T to E![]T
10638 if (prev_type->id == ZigTypeIdPointer &&10783 if (prev_type->id == ZigTypeIdPointer &&
10639 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&10784 prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
10785 prev_type->data.pointer.ptr_len == PtrLenSingle &&
10640 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||10786 ((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
10641 is_slice(cur_type)))10787 is_slice(cur_type)))
10642 {10788 {
...@@ -10644,7 +10790,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT...@@ -10644,7 +10790,8 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10644 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?10790 ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
10645 cur_type->data.error_union.payload_type : cur_type;10791 cur_type->data.error_union.payload_type : cur_type;
10646 ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;10792 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) &&
10648 types_match_const_cast_only(ira,10795 types_match_const_cast_only(ira,
10649 slice_ptr_type->data.pointer.child_type,10796 slice_ptr_type->data.pointer.child_type,
10650 array_type->data.array.child_type, source_node, false).id == ConstCastResultIdOk)10797 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...@@ -10667,6 +10814,50 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10667 continue;10814 continue;
10668 }10815 }
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
10670 // [N]T to []T10861 // [N]T to []T
10671 if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&10862 if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&
10672 (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||10863 (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...@@ -10715,16 +10906,34 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
10715 free(errors);10906 free(errors);
1071610907
10717 if (convert_to_const_slice) {10908 if (convert_to_const_slice) {
10718 assert(prev_inst->value.type->id == ZigTypeIdArray);10909 if (prev_inst->value.type->id == ZigTypeIdArray) {
10719 ZigType *ptr_type = get_pointer_to_type_extra(10910 ZigType *ptr_type = get_pointer_to_type_extra(
10720 ira->codegen, prev_inst->value.type->data.array.child_type,10911 ira->codegen, prev_inst->value.type->data.array.child_type,
10721 true, false, PtrLenUnknown,10912 true, false, PtrLenUnknown,
10722 0, 0, 0, false);10913 0, 0, 0, false);
10723 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);10914 ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
10724 if (err_set_type != nullptr) {10915 if (err_set_type != nullptr) {
10725 return get_error_union_type(ira->codegen, err_set_type, slice_type);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 }
10726 } else {10935 } else {
10727 return slice_type;10936 zig_unreachable();
10728 }10937 }
10729 } else if (err_set_type != nullptr) {10938 } else if (err_set_type != nullptr) {
10730 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {10939 if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
...@@ -10945,7 +11154,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -10945,7 +11154,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
10945 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;11154 result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
10946 result->value.data.x_ptr.data.base_array.array_val = pointee;11155 result->value.data.x_ptr.data.base_array.array_val = pointee;
10947 result->value.data.x_ptr.data.base_array.elem_index = 0;11156 result->value.data.x_ptr.data.base_array.elem_index = 0;
10948 result->value.data.x_ptr.data.base_array.is_cstr = false;
10949 return result;11157 return result;
10950 }11158 }
10951 }11159 }
...@@ -10957,31 +11165,31 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,...@@ -10957,31 +11165,31 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
10957}11165}
1095811166
10959static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,11167static 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)
10961{11169{
10962 Error err;11170 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,
10965 ResolveStatusAlignmentKnown)))11173 ResolveStatusAlignmentKnown)))
10966 {11174 {
10967 return ira->codegen->invalid_instruction;11175 return ira->codegen->invalid_instruction;
10968 }11176 }
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)) {11180 if (instr_is_comptime(array_ptr)) {
10973 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);11181 ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &array_ptr->value, source_instr->source_node);
10974 if (pointee == nullptr)11182 if (pointee == nullptr)
10975 return ira->codegen->invalid_instruction;11183 return ira->codegen->invalid_instruction;
10976 if (pointee->special != ConstValSpecialRuntime) {11184 if (pointee->special != ConstValSpecialRuntime) {
10977 assert(value->value.type->id == ZigTypeIdPointer);11185 assert(array_ptr->value.type->id == ZigTypeIdPointer);
10978 ZigType *array_type = value->value.type->data.pointer.child_type;11186 ZigType *array_type = array_ptr->value.type->data.pointer.child_type;
10979 assert(is_slice(wanted_type));11187 assert(is_slice(wanted_type));
10980 bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;11188 bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
1098111189
10982 IrInstruction *result = ir_const(ira, source_instr, wanted_type);11190 IrInstruction *result = ir_const(ira, source_instr, wanted_type);
10983 init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);11191 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;
10985 result->value.type = wanted_type;11193 result->value.type = wanted_type;
10986 return result;11194 return result;
10987 }11195 }
...@@ -10993,7 +11201,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc...@@ -10993,7 +11201,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
10993 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {11201 if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
10994 return result_loc_inst;11202 return result_loc_inst;
10995 }11203 }
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);
10997}11205}
1099811206
10999static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {11207static 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...@@ -11524,7 +11732,7 @@ static IrInstruction *ir_analyze_optional_wrap(IrAnalyze *ira, IrInstruction *so
11524 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,11732 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(&ira->new_irb,
11525 source_instr->scope, source_instr->source_node);11733 source_instr->scope, source_instr->source_node);
11526 const_instruction->base.value.special = ConstValSpecialStatic;11734 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)) {
11528 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);11736 copy_const_val(&const_instruction->base.value, val, val->data.x_ptr.mut == ConstPtrMutComptimeConst);
11529 } else {11737 } else {
11530 const_instruction->base.value.data.x_optional = val;11738 const_instruction->base.value.data.x_optional = val;
...@@ -12442,6 +12650,55 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -12442,6 +12650,55 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
12442 }12650 }
12443 break;12651 break;
12444 }12652 }
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 }
12445 case ConstCastResultIdFnIsGeneric:12702 case ConstCastResultIdFnIsGeneric:
12446 add_error_note(ira->codegen, parent_msg, source_node,12703 add_error_note(ira->codegen, parent_msg, source_node,
12447 buf_sprintf("only one of the functions is generic"));12704 buf_sprintf("only one of the functions is generic"));
...@@ -12458,6 +12715,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa...@@ -12458,6 +12715,7 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
12458 case ConstCastResultIdFnArgNoAlias: // TODO12715 case ConstCastResultIdFnArgNoAlias: // TODO
12459 case ConstCastResultIdUnresolvedInferredErrSet: // TODO12716 case ConstCastResultIdUnresolvedInferredErrSet: // TODO
12460 case ConstCastResultIdAsyncAllocatorType: // TODO12717 case ConstCastResultIdAsyncAllocatorType: // TODO
12718 case ConstCastResultIdArrayChild: // TODO
12461 break;12719 break;
12462 }12720 }
12463}12721}
...@@ -12584,8 +12842,55 @@ static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstr...@@ -12584,8 +12842,55 @@ static IrInstruction *ir_analyze_struct_literal_to_union(IrAnalyze *ira, IrInstr
12584 return ira->codegen->invalid_instruction;12842 return ira->codegen->invalid_instruction;
12585}12843}
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
12587static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,12892static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
12588 ZigType *wanted_type, IrInstruction *value, ResultLoc *result_loc)12893 ZigType *wanted_type, IrInstruction *value)
12589{12894{
12590 Error err;12895 Error err;
12591 ZigType *actual_type = value->value.type;12896 ZigType *actual_type = value->value.type;
...@@ -12631,12 +12936,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12631,12 +12936,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12631 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,12936 if (types_match_const_cast_only(ira, wanted_child_type, actual_type, source_node,
12632 false).id == ConstCastResultIdOk)12937 false).id == ConstCastResultIdOk)
12633 {12938 {
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);
12635 } else if (actual_type->id == ZigTypeIdComptimeInt ||12940 } else if (actual_type->id == ZigTypeIdComptimeInt ||
12636 actual_type->id == ZigTypeIdComptimeFloat)12941 actual_type->id == ZigTypeIdComptimeFloat)
12637 {12942 {
12638 if (ir_num_lit_fits_in_other_type(ira, value, wanted_child_type, true)) {12943 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);
12640 } else {12945 } else {
12641 return ira->codegen->invalid_instruction;12946 return ira->codegen->invalid_instruction;
12642 }12947 }
...@@ -12660,7 +12965,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12660,7 +12965,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12660 wanted_child_type);12965 wanted_child_type);
12661 if (type_is_invalid(cast1->value.type))12966 if (type_is_invalid(cast1->value.type))
12662 return ira->codegen->invalid_instruction;12967 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);
12664 }12969 }
12665 }12970 }
12666 }12971 }
...@@ -12670,12 +12975,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12670,12 +12975,12 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12670 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,12975 if (types_match_const_cast_only(ira, wanted_type->data.error_union.payload_type, actual_type,
12671 source_node, false).id == ConstCastResultIdOk)12976 source_node, false).id == ConstCastResultIdOk)
12672 {12977 {
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);
12674 } else if (actual_type->id == ZigTypeIdComptimeInt ||12979 } else if (actual_type->id == ZigTypeIdComptimeInt ||
12675 actual_type->id == ZigTypeIdComptimeFloat)12980 actual_type->id == ZigTypeIdComptimeFloat)
12676 {12981 {
12677 if (ir_num_lit_fits_in_other_type(ira, value, wanted_type->data.error_union.payload_type, true)) {12982 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);
12679 } else {12984 } else {
12680 return ira->codegen->invalid_instruction;12985 return ira->codegen->invalid_instruction;
12681 }12986 }
...@@ -12693,11 +12998,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12693,11 +12998,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12693 actual_type->id == ZigTypeIdComptimeInt ||12998 actual_type->id == ZigTypeIdComptimeInt ||
12694 actual_type->id == ZigTypeIdComptimeFloat)12999 actual_type->id == ZigTypeIdComptimeFloat)
12695 {13000 {
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);
12697 if (type_is_invalid(cast1->value.type))13002 if (type_is_invalid(cast1->value.type))
12698 return ira->codegen->invalid_instruction;13003 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);
12701 if (type_is_invalid(cast2->value.type))13006 if (type_is_invalid(cast2->value.type))
12702 return ira->codegen->invalid_instruction;13007 return ira->codegen->invalid_instruction;
1270313008
...@@ -12770,7 +13075,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12770,7 +13075,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12770 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);13075 return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
12771 }13076 }
1277213077
12773
12774 // cast from [N]T to []const T13078 // cast from [N]T to []const T
12775 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this13079 // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
12776 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {13080 if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
...@@ -12780,7 +13084,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12780,7 +13084,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12780 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,13084 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
12781 source_node, false).id == ConstCastResultIdOk)13085 source_node, false).id == ConstCastResultIdOk)
12782 {13086 {
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);
12784 }13088 }
12785 }13089 }
1278613090
...@@ -12797,11 +13101,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12797,11 +13101,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12797 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,13101 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
12798 source_node, false).id == ConstCastResultIdOk)13102 source_node, false).id == ConstCastResultIdOk)
12799 {13103 {
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);
12801 if (type_is_invalid(cast1->value.type))13105 if (type_is_invalid(cast1->value.type))
12802 return ira->codegen->invalid_instruction;13106 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);
12805 if (type_is_invalid(cast2->value.type))13109 if (type_is_invalid(cast2->value.type))
12806 return ira->codegen->invalid_instruction;13110 return ira->codegen->invalid_instruction;
1280713111
...@@ -12809,23 +13113,50 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12809,23 +13113,50 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12809 }13113 }
12810 }13114 }
1281113115
12812 // *[N]T to [*]T and [*c]T13116 // *[N]T to ?[]const T
12813 if (wanted_type->id == ZigTypeIdPointer &&13117 if (wanted_type->id == ZigTypeIdOptional &&
12814 (wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&13118 is_slice(wanted_type->data.maybe.child_type) &&
12815 actual_type->id == ZigTypeIdPointer &&13119 actual_type->id == ZigTypeIdPointer &&
12816 actual_type->data.pointer.ptr_len == PtrLenSingle &&13120 actual_type->data.pointer.ptr_len == PtrLenSingle &&
12817 actual_type->data.pointer.child_type->id == ZigTypeIdArray)13121 actual_type->data.pointer.child_type->id == ZigTypeIdArray)
12818 {13122 {
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))
12820 return ira->codegen->invalid_instruction;13125 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))
12822 return ira->codegen->invalid_instruction;13129 return ira->codegen->invalid_instruction;
12823 if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&13130
12824 types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,13131 return cast2;
12825 actual_type->data.pointer.child_type->data.array.child_type, source_node,13132 }
12826 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)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)))
12827 {13148 {
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 }
12829 }13160 }
12830 }13161 }
1283113162
...@@ -12870,17 +13201,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12870,17 +13201,17 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12870 }13201 }
12871 if (ok_align) {13202 if (ok_align) {
12872 if (wanted_type->id == ZigTypeIdErrorUnion) {13203 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);
12874 if (type_is_invalid(cast1->value.type))13205 if (type_is_invalid(cast1->value.type))
12875 return ira->codegen->invalid_instruction;13206 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);
12878 if (type_is_invalid(cast2->value.type))13209 if (type_is_invalid(cast2->value.type))
12879 return ira->codegen->invalid_instruction;13210 return ira->codegen->invalid_instruction;
1288013211
12881 return cast2;13212 return cast2;
12882 } else {13213 } 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);
12884 }13215 }
12885 }13216 }
12886 }13217 }
...@@ -12921,7 +13252,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12921,7 +13252,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12921 ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);13252 ok_align = get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, slice_ptr_type);
12922 }13253 }
12923 if (ok_align) {13254 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);
12925 }13256 }
12926 }13257 }
12927 }13258 }
...@@ -12977,11 +13308,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12977,11 +13308,11 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12977 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,13308 types_match_const_cast_only(ira, ptr_type->data.pointer.child_type, actual_type->data.array.child_type,
12978 source_node, false).id == ConstCastResultIdOk)13309 source_node, false).id == ConstCastResultIdOk)
12979 {13310 {
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);
12981 if (type_is_invalid(cast1->value.type))13312 if (type_is_invalid(cast1->value.type))
12982 return ira->codegen->invalid_instruction;13313 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);
12985 if (type_is_invalid(cast2->value.type))13316 if (type_is_invalid(cast2->value.type))
12986 return ira->codegen->invalid_instruction;13317 return ira->codegen->invalid_instruction;
1298713318
...@@ -12993,7 +13324,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -12993,7 +13324,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
12993 if (wanted_type->id == ZigTypeIdErrorUnion &&13324 if (wanted_type->id == ZigTypeIdErrorUnion &&
12994 actual_type->id == ZigTypeIdErrorSet)13325 actual_type->id == ZigTypeIdErrorSet)
12995 {13326 {
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);
12997 }13328 }
1299813329
12999 // cast from typed number to integer or float literal.13330 // cast from typed number to integer or float literal.
...@@ -13019,7 +13350,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -13019,7 +13350,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
13019 if (result == ira->codegen->invalid_instruction) 13350 if (result == ira->codegen->invalid_instruction)
13020 return result;13351 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);
13023 }13354 }
1302413355
13025 // cast from enum literal to error union when payload is an enum13356 // 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...@@ -13030,7 +13361,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
13030 if (result == ira->codegen->invalid_instruction) 13361 if (result == ira->codegen->invalid_instruction)
13031 return result;13362 return result;
13032 13363
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);
13034 }13365 }
1303513366
13036 // cast from union to the enum type of the union13367 // cast from union to the enum type of the union
...@@ -13060,35 +13391,39 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -13060,35 +13391,39 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
13060 types_match_const_cast_only(ira, array_type->data.array.child_type,13391 types_match_const_cast_only(ira, array_type->data.array.child_type,
13061 actual_type->data.pointer.child_type, source_node,13392 actual_type->data.pointer.child_type, source_node,
13062 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&13393 !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk &&
13063 // This should be the job of `types_match_const_cast_only`13394 // `types_match_const_cast_only` only gets info for child_types
13064 // but `types_match_const_cast_only` only gets info for child_types13395 (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
13065 ((wanted_type->data.pointer.is_const && actual_type->data.pointer.is_const) ||13396 (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile))
13066 !actual_type->data.pointer.is_const))
13067 {13397 {
13068 if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type,13398 if ((err = ir_cast_ptr_align(ira, source_instr, wanted_type, actual_type, value->source_node)))
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));
13086 return ira->codegen->invalid_instruction;13399 return ira->codegen->invalid_instruction;
13087 }13400
13088 return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);13401 return ir_analyze_ptr_to_array(ira, source_instr, value, wanted_type);
13089 }13402 }
13090 }13403 }
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
13092 // cast from *T and [*]T to *c_void and ?*c_void13427 // cast from *T and [*]T to *c_void and ?*c_void
13093 // but don't do it if the actual type is a double pointer13428 // but don't do it if the actual type is a double pointer
13094 if (is_pointery_and_elem_is_not_pointery(actual_type)) {13429 if (is_pointery_and_elem_is_not_pointery(actual_type)) {
...@@ -13127,7 +13462,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -13127,7 +13462,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
13127 types_match_const_cast_only(ira, wanted_type->data.array.child_type,13462 types_match_const_cast_only(ira, wanted_type->data.array.child_type,
13128 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)13463 actual_type->data.vector.elem_type, source_node, false).id == ConstCastResultIdOk)
13129 {13464 {
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);
13131 }13466 }
1313213467
13133 // cast from [N]T to @Vector(N, T)13468 // cast from [N]T to @Vector(N, T)
...@@ -13188,8 +13523,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -13188,8 +13523,8 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
13188 return ira->codegen->invalid_instruction;13523 return ira->codegen->invalid_instruction;
13189}13524}
1319013525
13191static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *source_instr,13526static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr,
13192 IrInstruction *value, ZigType *expected_type, ResultLoc *result_loc)13527 IrInstruction *value, ZigType *expected_type)
13193{13528{
13194 assert(value);13529 assert(value);
13195 assert(value != ira->codegen->invalid_instruction);13530 assert(value != ira->codegen->invalid_instruction);
...@@ -13203,11 +13538,11 @@ static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction...@@ -13203,11 +13538,11 @@ static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction
13203 if (value->value.type->id == ZigTypeIdUnreachable)13538 if (value->value.type->id == ZigTypeIdUnreachable)
13204 return value;13539 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);
13207}13542}
1320813543
13209static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) {13544static 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);
13211}13546}
1321213547
13213static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr,13548static 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...@@ -13242,6 +13577,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
13242 }13577 }
13243 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {13578 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
13244 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);13579 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 }
13245 if (pointee->special != ConstValSpecialRuntime) {13583 if (pointee->special != ConstValSpecialRuntime) {
13246 IrInstruction *result = ir_const(ira, source_instruction, child_type);13584 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1324713585
...@@ -14519,8 +14857,6 @@ static bool ok_float_op(IrBinOp op) {...@@ -14519,8 +14857,6 @@ static bool ok_float_op(IrBinOp op) {
14519}14857}
1452014858
14521static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {14859static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
14522 if (lhs_type->id != ZigTypeIdPointer)
14523 return false;
14524 switch (op) {14860 switch (op) {
14525 case IrBinOpAdd:14861 case IrBinOpAdd:
14526 case IrBinOpSub:14862 case IrBinOpSub:
...@@ -14528,14 +14864,16 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {...@@ -14528,14 +14864,16 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
14528 default:14864 default:
14529 return false;14865 return false;
14530 }14866 }
14867 if (lhs_type->id != ZigTypeIdPointer)
14868 return false;
14531 switch (lhs_type->data.pointer.ptr_len) {14869 switch (lhs_type->data.pointer.ptr_len) {
14532 case PtrLenSingle:14870 case PtrLenSingle:
14533 return false;14871 return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;
14534 case PtrLenUnknown:14872 case PtrLenUnknown:
14535 case PtrLenC:14873 case PtrLenC:
14536 break;14874 return true;
14537 }14875 }
14538 return true;14876 zig_unreachable();
14539}14877}
1454014878
14541static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {14879static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
...@@ -14797,6 +15135,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14797,6 +15135,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14797 if (!op2_val)15135 if (!op2_val)
14798 return ira->codegen->invalid_instruction;15136 return ira->codegen->invalid_instruction;
1479915137
15138 ConstExprValue *sentinel1 = nullptr;
14800 ConstExprValue *op1_array_val;15139 ConstExprValue *op1_array_val;
14801 size_t op1_array_index;15140 size_t op1_array_index;
14802 size_t op1_array_end;15141 size_t op1_array_end;
...@@ -14806,15 +15145,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14806,15 +15145,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14806 op1_array_val = op1_val;15145 op1_array_val = op1_val;
14807 op1_array_index = 0;15146 op1_array_index = 0;
14808 op1_array_end = op1_type->data.array.len;15147 op1_array_end = op1_type->data.array.len;
15148 sentinel1 = op1_type->data.array.sentinel;
14809 } else if (op1_type->id == ZigTypeIdPointer &&15149 } else if (op1_type->id == ZigTypeIdPointer &&
14810 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&15150 op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
14811 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&15151 op1_type->data.pointer.sentinel != nullptr &&
14812 op1_val->data.x_ptr.data.base_array.is_cstr)15152 op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
14813 {15153 {
14814 child_type = op1_type->data.pointer.child_type;15154 child_type = op1_type->data.pointer.child_type;
14815 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;15155 op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
14816 op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;15156 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;
14818 } else if (is_slice(op1_type)) {15159 } else if (is_slice(op1_type)) {
14819 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;15160 ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
14820 child_type = ptr_type->data.pointer.child_type;15161 child_type = ptr_type->data.pointer.child_type;
...@@ -14824,12 +15165,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14824,12 +15165,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14824 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;15165 op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
14825 ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];15166 ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
14826 op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);15167 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;
14827 } else {15180 } else {
14828 ir_add_error(ira, op1,15181 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)));
14830 return ira->codegen->invalid_instruction;15183 return ira->codegen->invalid_instruction;
14831 }15184 }
1483215185
15186 ConstExprValue *sentinel2 = nullptr;
14833 ConstExprValue *op2_array_val;15187 ConstExprValue *op2_array_val;
14834 size_t op2_array_index;15188 size_t op2_array_index;
14835 size_t op2_array_end;15189 size_t op2_array_end;
...@@ -14839,15 +15193,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14839,15 +15193,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14839 op2_array_val = op2_val;15193 op2_array_val = op2_val;
14840 op2_array_index = 0;15194 op2_array_index = 0;
14841 op2_array_end = op2_array_val->type->data.array.len;15195 op2_array_end = op2_array_val->type->data.array.len;
15196 sentinel2 = op2_type->data.array.sentinel;
14842 } else if (op2_type->id == ZigTypeIdPointer &&15197 } else if (op2_type->id == ZigTypeIdPointer &&
14843 op2_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&15198 op2_type->data.pointer.sentinel != nullptr &&
14844 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&15199 op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
14845 op2_val->data.x_ptr.data.base_array.is_cstr)
14846 {15200 {
14847 op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;15201 op2_type_valid = op2_type->data.pointer.child_type == child_type;
14848 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;15202 op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
14849 op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;15203 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;
14851 } else if (is_slice(op2_type)) {15207 } else if (is_slice(op2_type)) {
14852 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;15208 ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
14853 op2_type_valid = ptr_type->data.pointer.child_type == child_type;15209 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...@@ -14857,6 +15213,20 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14857 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;15213 op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
14858 ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];15214 ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];
14859 op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);15215 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;
14860 } else {15230 } else {
14861 ir_add_error(ira, op2,15231 ir_add_error(ira, op2,
14862 buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));15232 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...@@ -14869,6 +15239,19 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14869 return ira->codegen->invalid_instruction;15239 return ira->codegen->invalid_instruction;
14870 }15240 }
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
14872 // The type of result is populated in the following if blocks15255 // The type of result is populated in the following if blocks
14873 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);15256 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
14874 ConstExprValue *out_val = &result->value;15257 ConstExprValue *out_val = &result->value;
...@@ -14876,16 +15259,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i...@@ -14876,16 +15259,25 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14876 ConstExprValue *out_array_val;15259 ConstExprValue *out_array_val;
14877 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);15260 size_t new_len = (op1_array_end - op1_array_index) + (op2_array_end - op2_array_index);
14878 if (op1_type->id == ZigTypeIdArray || op2_type->id == ZigTypeIdArray) {15261 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
14881 out_array_val = out_val;15264 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);
14882 } else if (is_slice(op1_type) || is_slice(op2_type)) {15273 } else if (is_slice(op1_type) || is_slice(op2_type)) {
14883 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,15274 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen, child_type,
14884 true, false, PtrLenUnknown, 0, 0, 0, false);15275 true, false, PtrLenUnknown, 0, 0, 0, false,
15276 VECTOR_INDEX_NONE, nullptr, sentinel);
14885 result->value.type = get_slice_type(ira->codegen, ptr_type);15277 result->value.type = get_slice_type(ira->codegen, ptr_type);
14886 out_array_val = create_const_vals(1);15278 out_array_val = create_const_vals(1);
14887 out_array_val->special = ConstValSpecialStatic;15279 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
14890 out_val->data.x_struct.fields = alloc_const_vals_ptrs(2);15282 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...@@ -14899,46 +15291,54 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
14899 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;15291 out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;
14900 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);15292 bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
14901 } else {15293 } else {
14902 new_len += 1; // null byte15294 result->value.type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown,
1490315295 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr, sentinel);
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);
1490615296
14907 out_array_val = create_const_vals(1);15297 out_array_val = create_const_vals(1);
14908 out_array_val->special = ConstValSpecialStatic;15298 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);
14910 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;15300 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
14911 out_val->data.x_ptr.data.base_array.is_cstr = true;
14912 out_val->data.x_ptr.data.base_array.array_val = out_array_val;15301 out_val->data.x_ptr.data.base_array.array_val = out_array_val;
14913 out_val->data.x_ptr.data.base_array.elem_index = 0;15302 out_val->data.x_ptr.data.base_array.elem_index = 0;
14914 }15303 }
1491515304
14916 if (op1_array_val->data.x_array.special == ConstArraySpecialUndef &&15305 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 {
14918 out_array_val->data.x_array.special = ConstArraySpecialUndef;15308 out_array_val->data.x_array.special = ConstArraySpecialUndef;
14919 return result;15309 return result;
14920 }15310 }
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);
14923 // TODO handle the buf case here for an optimization15314 // TODO handle the buf case here for an optimization
14924 expand_undef_array(ira->codegen, op1_array_val);15315 expand_undef_array(ira->codegen, op1_array_val);
14925 expand_undef_array(ira->codegen, op2_array_val);15316 expand_undef_array(ira->codegen, op2_array_val);
1492615317
14927 size_t next_index = 0;15318 size_t next_index = 0;
14928 for (size_t i = op1_array_index; i < op1_array_end; i += 1, next_index += 1) {15319 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],15320 ConstExprValue *elem_dest_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);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;
14931 }15325 }
14932 for (size_t i = op2_array_index; i < op2_array_end; i += 1, next_index += 1) {15326 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],15327 ConstExprValue *elem_dest_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);15328 copy_const_val(elem_dest_val, &op2_array_val->data.x_array.data.s_none.elements[i], false);
14935 }15329 elem_dest_val->parent.id = ConstParentIdArray;
14936 if (next_index < new_len) {15330 elem_dest_val->parent.data.p_array.array_val = out_array_val;
14937 ConstExprValue *null_byte = &out_array_val->data.x_array.data.s_none.elements[next_index];15331 elem_dest_val->parent.data.p_array.elem_index = next_index;
14938 init_const_unsigned_negative(null_byte, child_type, 0, false);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;
14939 next_index += 1;15339 next_index += 1;
14940 }15340 }
14941 assert(next_index == new_len);15341 assert(next_index == full_len);
1494215342
14943 return result;15343 return result;
14944}15344}
...@@ -14952,20 +15352,34 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -14952,20 +15352,34 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
14952 if (type_is_invalid(op2->value.type))15352 if (type_is_invalid(op2->value.type))
14953 return ira->codegen->invalid_instruction;15353 return ira->codegen->invalid_instruction;
1495415354
14955 ConstExprValue *array_val = ir_resolve_const(ira, op1, UndefBad);15355 bool want_ptr_to_array = false;
14956 if (!array_val)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)));
14957 return ira->codegen->invalid_instruction;15376 return ira->codegen->invalid_instruction;
15377 }
1495815378
14959 uint64_t mult_amt;15379 uint64_t mult_amt;
14960 if (!ir_resolve_usize(ira, op2, &mult_amt))15380 if (!ir_resolve_usize(ira, op2, &mult_amt))
14961 return ira->codegen->invalid_instruction;15381 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
14969 uint64_t old_array_len = array_type->data.array.len;15383 uint64_t old_array_len = array_type->data.array.len;
14970 uint64_t new_array_len;15384 uint64_t new_array_len;
1497115385
...@@ -14975,42 +15389,58 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *...@@ -14975,42 +15389,58 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
14975 }15389 }
1497615390
14977 ZigType *child_type = array_type->data.array.child_type;15391 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,15395 IrInstruction *array_result;
14980 get_array_type(ira->codegen, child_type, new_array_len));15396 if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
14981 ConstExprValue *out_val = &result->value;15397 array_result = ir_const_undef(ira, &instruction->base, result_array_type);
14982 if (array_val->data.x_array.special == ConstArraySpecialUndef) {15398 } else {
14983 out_val->data.x_array.special = ConstArraySpecialUndef;15399 array_result = ir_const(ira, &instruction->base, result_array_type);
14984 return result;15400 ConstExprValue *out_val = &array_result->value;
14985 }
1498615401
14987 switch (type_has_one_possible_value(ira->codegen, result->value.type)) {15402 switch (type_has_one_possible_value(ira->codegen, result_array_type)) {
14988 case OnePossibleValueInvalid:15403 case OnePossibleValueInvalid:
14989 return ira->codegen->invalid_instruction;15404 return ira->codegen->invalid_instruction;
14990 case OnePossibleValueYes:15405 case OnePossibleValueYes:
14991 return result;15406 goto skip_computation;
14992 case OnePossibleValueNo:15407 case OnePossibleValueNo:
14993 break;15408 break;
14994 }15409 }
1499515410
14996 // TODO optimize the buf case15411 // TODO optimize the buf case
14997 expand_undef_array(ira->codegen, array_val);15412 expand_undef_array(ira->codegen, array_val);
14998 out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len);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;15416 uint64_t i = 0;
15001 for (uint64_t x = 0; x < mult_amt; x += 1) {15417 for (uint64_t x = 0; x < mult_amt; x += 1) {
15002 for (uint64_t y = 0; y < old_array_len; y += 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) {
15003 ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];15430 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);
15005 elem_dest_val->parent.id = ConstParentIdArray;15432 elem_dest_val->parent.id = ConstParentIdArray;
15006 elem_dest_val->parent.data.p_array.array_val = out_val;15433 elem_dest_val->parent.data.p_array.array_val = out_val;
15007 elem_dest_val->parent.data.p_array.elem_index = i;15434 elem_dest_val->parent.data.p_array.elem_index = i;
15008 i += 1;15435 i += 1;
15009 }15436 }
15010 }15437 }
15011 assert(i == new_array_len);15438skip_computation:
1501215439 if (want_ptr_to_array) {
15013 return result;15440 return ir_get_ref(ira, &instruction->base, array_result, true, false);
15441 } else {
15442 return array_result;
15443 }
15014}15444}
1501515445
15016static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,15446static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
...@@ -15909,7 +16339,19 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe...@@ -15909,7 +16339,19 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
15909 if (!type_has_bits(value_type)) {16339 if (!type_has_bits(value_type)) {
15910 parent_ptr_align = 0;16340 parent_ptr_align = 0;
15911 }16341 }
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,
15913 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,16355 parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
15914 parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);16356 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...@@ -17283,6 +17725,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
17283 assert(out_val->type != nullptr);17725 assert(out_val->type != nullptr);
1728417726
17285 ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);17727 ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
17728 src_assert(pointee->type != nullptr, source_node);
1728617729
17287 if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))17730 if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
17288 return ErrorSemanticAnalyzeFail;17731 return ErrorSemanticAnalyzeFail;
...@@ -17293,7 +17736,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source...@@ -17293,7 +17736,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
17293 size_t dst_size = type_size(codegen, out_val->type);17736 size_t dst_size = type_size(codegen, out_val->type);
1729417737
17295 if (dst_size <= src_size) {17738 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)) {
17297 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);17740 copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
17298 return ErrorNone;17741 return ErrorNone;
17299 }17742 }
...@@ -17882,13 +18325,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi...@@ -17882,13 +18325,16 @@ static IrInstruction *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructi
1788218325
17883static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {18326static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) {
17884 assert(ptr_type->id == ZigTypeIdPointer);18327 assert(ptr_type->id == ZigTypeIdPointer);
17885 return get_pointer_to_type_extra(g,18328 return get_pointer_to_type_extra2(g,
17886 ptr_type->data.pointer.child_type,18329 ptr_type->data.pointer.child_type,
17887 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18330 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
17888 ptr_type->data.pointer.ptr_len,18331 ptr_type->data.pointer.ptr_len,
17889 new_align,18332 new_align,
17890 ptr_type->data.pointer.bit_offset_in_host, ptr_type->data.pointer.host_int_bytes,18333 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);
17892}18338}
1789318339
17894static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) {18340static 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...@@ -18044,6 +18490,12 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18044 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);18490 uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
18045 if (array_type->id == ZigTypeIdArray) {18491 if (array_type->id == ZigTypeIdArray) {
18046 uint64_t array_len = array_type->data.array.len;18492 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 }
18047 if (index >= array_len) {18499 if (index >= array_len) {
18048 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,18500 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
18049 buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,18501 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...@@ -18059,7 +18511,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18059 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18511 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18060 elem_ptr_instruction->ptr_len,18512 elem_ptr_instruction->ptr_len,
18061 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,18513 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, (uint32_t)index,
18062 nullptr);18514 nullptr, nullptr);
18063 } else if (return_type->data.pointer.explicit_alignment != 0) {18515 } else if (return_type->data.pointer.explicit_alignment != 0) {
18064 // figure out the largest alignment possible18516 // figure out the largest alignment possible
1806518517
...@@ -18166,18 +18618,37 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18166,18 +18618,37 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18166 case ConstPtrSpecialDiscard:18618 case ConstPtrSpecialDiscard:
18167 zig_unreachable();18619 zig_unreachable();
18168 case ConstPtrSpecialRef:18620 case ConstPtrSpecialRef:
18169 mem_size = 1;18621 if (array_ptr_val->data.x_ptr.data.ref.pointee->type->id == ZigTypeIdArray) {
18170 old_size = 1;18622 ConstExprValue *array_val = array_ptr_val->data.x_ptr.data.ref.pointee;
18171 new_index = index;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;18631 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
18174 out_val->data.x_ptr.data.ref.pointee = array_ptr_val->data.x_ptr.data.ref.pointee;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 }
18175 break;18642 break;
18176 case ConstPtrSpecialBaseArray:18643 case ConstPtrSpecialBaseArray:
18177 {18644 {
18178 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;18645 size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
18179 new_index = offset + index;18646 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 }
18181 old_size = mem_size - offset;18652 old_size = mem_size - offset;
1818218653
18183 assert(array_ptr_val->data.x_ptr.data.base_array.array_val);18654 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...@@ -18186,8 +18657,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18186 out_val->data.x_ptr.data.base_array.array_val =18657 out_val->data.x_ptr.data.base_array.array_val =
18187 array_ptr_val->data.x_ptr.data.base_array.array_val;18658 array_ptr_val->data.x_ptr.data.base_array.array_val;
18188 out_val->data.x_ptr.data.base_array.elem_index = new_index;18659 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
18192 break;18661 break;
18193 }18662 }
...@@ -18225,8 +18694,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18225,8 +18694,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18225 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];18694 ConstExprValue *len_field = array_ptr_val->data.x_struct.fields[slice_len_index];
18226 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);18695 IrInstruction *result = ir_const(ira, &elem_ptr_instruction->base, return_type);
18227 ConstExprValue *out_val = &result->value;18696 ConstExprValue *out_val = &result->value;
18697 ZigType *slice_ptr_type = array_type->data.structure.fields[slice_ptr_index]->type_entry;
18228 uint64_t slice_len = bigint_as_u64(&len_field->data.x_bigint);18698 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) {
18230 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,18702 ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
18231 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,18703 buf_sprintf("index %" ZIG_PRI_u64 " outside slice of size %" ZIG_PRI_u64,
18232 index, slice_len));18704 index, slice_len));
...@@ -18245,14 +18717,17 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18245,14 +18717,17 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18245 {18717 {
18246 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;18718 size_t offset = ptr_field->data.x_ptr.data.base_array.elem_index;
18247 uint64_t new_index = offset + index;18719 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,
18249 &elem_ptr_instruction->base);18725 &elem_ptr_instruction->base);
18726 }
18250 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;18727 out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
18251 out_val->data.x_ptr.data.base_array.array_val =18728 out_val->data.x_ptr.data.base_array.array_val =
18252 ptr_field->data.x_ptr.data.base_array.array_val;18729 ptr_field->data.x_ptr.data.base_array.array_val;
18253 out_val->data.x_ptr.data.base_array.elem_index = new_index;18730 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;
18256 break;18731 break;
18257 }18732 }
18258 case ConstPtrSpecialBaseStruct:18733 case ConstPtrSpecialBaseStruct:
...@@ -18301,7 +18776,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct...@@ -18301,7 +18776,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
18301 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,18776 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile,
18302 elem_ptr_instruction->ptr_len,18777 elem_ptr_instruction->ptr_len,
18303 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,18778 get_ptr_align(ira->codegen, ptr_type), 0, host_vec_len, false, VECTOR_INDEX_RUNTIME,
18304 nullptr);18779 nullptr, nullptr);
18305 } else {18780 } else {
18306 // runtime known element index18781 // runtime known element index
18307 switch (type_requires_comptime(ira->codegen, return_type)) {18782 switch (type_requires_comptime(ira->codegen, return_type)) {
...@@ -18505,7 +18980,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n...@@ -18505,7 +18980,7 @@ static IrInstruction *ir_analyze_inferred_field_ptr(IrAnalyze *ira, Buf *field_n
18505 ZigType *elem_type = ira->codegen->builtin_types.entry_var;18980 ZigType *elem_type = ira->codegen->builtin_types.entry_var;
18506 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,18981 ZigType *field_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
18507 container_ptr_type->data.pointer.is_const, container_ptr_type->data.pointer.is_volatile,18982 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
18510 if (instr_is_comptime(container_ptr)) {18985 if (instr_is_comptime(container_ptr)) {
18511 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);18986 IrInstruction *result = ir_const(ira, source_instr, field_ptr_type);
...@@ -19287,6 +19762,12 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,...@@ -19287,6 +19762,12 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira,
19287 return ira->codegen->invalid_instruction;19762 return ira->codegen->invalid_instruction;
19288 }19763 }
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
19290 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;19771 lazy_slice_type->elem_type = slice_type_instruction->child_type->child;
19291 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)19772 if (ir_resolve_type_lazy(ira, lazy_slice_type->elem_type) == nullptr)
19292 return ira->codegen->invalid_instruction;19773 return ira->codegen->invalid_instruction;
...@@ -19368,6 +19849,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -19368,6 +19849,22 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
19368 ZigType *child_type = ir_resolve_type(ira, child_type_value);19849 ZigType *child_type = ir_resolve_type(ira, child_type_value);
19369 if (type_is_invalid(child_type))19850 if (type_is_invalid(child_type))
19370 return ira->codegen->invalid_instruction;19851 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
19371 switch (child_type->id) {19868 switch (child_type->id) {
19372 case ZigTypeIdInvalid: // handled above19869 case ZigTypeIdInvalid: // handled above
19373 zig_unreachable();19870 zig_unreachable();
...@@ -19403,7 +19900,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,...@@ -19403,7 +19900,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
19403 {19900 {
19404 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))19901 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
19405 return ira->codegen->invalid_instruction;19902 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);
19407 return ir_const_type(ira, &array_type_instruction->base, result_type);19904 return ir_const_type(ira, &array_type_instruction->base, result_type);
19408 }19905 }
19409 }19906 }
...@@ -19476,13 +19973,24 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns...@@ -19476,13 +19973,24 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
19476 return ir_analyze_test_non_null(ira, &instruction->base, value);19973 return ir_analyze_test_non_null(ira, &instruction->base, value);
19477}19974}
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
19479static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,19990static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
19480 IrInstruction *base_ptr, bool safety_check_on, bool initializing)19991 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
19481{19992{
19482 ZigType *ptr_type = base_ptr->value.type;19993 ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr);
19483 assert(ptr_type->id == ZigTypeIdPointer);
19484
19485 ZigType *type_entry = ptr_type->data.pointer.child_type;
19486 if (type_is_invalid(type_entry))19994 if (type_is_invalid(type_entry))
19487 return ira->codegen->invalid_instruction;19995 return ira->codegen->invalid_instruction;
1948819996
...@@ -19520,9 +20028,10 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr...@@ -19520,9 +20028,10 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
1952020028
19521 ZigType *child_type = type_entry->data.maybe.child_type;20029 ZigType *child_type = type_entry->data.maybe.child_type;
19522 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,20030 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
19527 if (instr_is_comptime(base_ptr)) {20036 if (instr_is_comptime(base_ptr)) {
19528 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);20037 ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
...@@ -20479,7 +20988,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -20479,7 +20988,7 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
20479 if (container_type->id == ZigTypeIdArray) {20988 if (container_type->id == ZigTypeIdArray) {
20480 ZigType *child_type = container_type->data.array.child_type;20989 ZigType *child_type = container_type->data.array.child_type;
20481 if (container_type->data.array.len != elem_count) {20990 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
20484 ir_add_error(ira, &instruction->base,20993 ir_add_error(ira, &instruction->base,
20485 buf_sprintf("expected %s literal, found %s literal",20994 buf_sprintf("expected %s literal, found %s literal",
...@@ -20657,7 +21166,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct...@@ -20657,7 +21166,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
20657 return ira->codegen->invalid_instruction;21166 return ira->codegen->invalid_instruction;
20658 ErrorTableEntry *err = casted_value->value.data.x_err_set;21167 ErrorTableEntry *err = casted_value->value.data.x_err_set;
20659 if (!err->cached_error_name_val) {21168 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;
20661 err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);21170 err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
20662 }21171 }
20663 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);21172 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
...@@ -20686,7 +21195,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns...@@ -20686,7 +21195,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
20686 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))21195 if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
20687 return ira->codegen->invalid_instruction;21196 return ira->codegen->invalid_instruction;
20688 TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);21197 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;
20690 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);21199 IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
20691 init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);21200 init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);
20692 return result;21201 return result;
...@@ -20966,7 +21475,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -20966,7 +21475,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
2096621475
20967 ConstExprValue *declaration_array = create_const_vals(1);21476 ConstExprValue *declaration_array = create_const_vals(1);
20968 declaration_array->special = ConstValSpecialStatic;21477 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);
20970 declaration_array->data.x_array.special = ConstArraySpecialNone;21479 declaration_array->data.x_array.special = ConstArraySpecialNone;
20971 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);21480 declaration_array->data.x_array.data.s_none.elements = create_const_vals(declaration_count);
20972 init_const_slice(ira->codegen, out_val, declaration_array, 0, declaration_count, false);21481 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...@@ -20991,7 +21500,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
20991 declaration_val->type = type_info_declaration_type;21500 declaration_val->type = type_info_declaration_type;
2099221501
20993 ConstExprValue **inner_fields = alloc_const_vals_ptrs(3);21502 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;
20995 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true);21504 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true);
20996 inner_fields[1]->special = ConstValSpecialStatic;21505 inner_fields[1]->special = ConstValSpecialStatic;
20997 inner_fields[1]->type = ira->codegen->builtin_types.entry_bool;21506 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...@@ -21094,7 +21603,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
21094 fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));21603 fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
21095 if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {21604 if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {
21096 fn_decl_fields[6]->data.x_optional = create_const_vals(1);21605 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;
21098 init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0,21607 init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0,
21099 buf_len(fn_node->lib_name), true);21608 buf_len(fn_node->lib_name), true);
21100 } else {21609 } else {
...@@ -21111,7 +21620,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr...@@ -21111,7 +21620,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
21111 ConstExprValue *fn_arg_name_array = create_const_vals(1);21620 ConstExprValue *fn_arg_name_array = create_const_vals(1);
21112 fn_arg_name_array->special = ConstValSpecialStatic;21621 fn_arg_name_array->special = ConstValSpecialStatic;
21113 fn_arg_name_array->type = get_array_type(ira->codegen,21622 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);
21115 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;21624 fn_arg_name_array->data.x_array.special = ConstArraySpecialNone;
21116 fn_arg_name_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);21625 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...@@ -21121,7 +21630,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
21121 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);21630 ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
21122 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];21631 ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
21123 ConstExprValue *arg_name = create_const_str_lit(ira->codegen,21632 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;
21125 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true);21634 init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true);
21126 fn_arg_name_val->parent.id = ConstParentIdArray;21635 fn_arg_name_val->parent.id = ConstParentIdArray;
21127 fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;21636 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...@@ -21210,7 +21719,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
21210 result->special = ConstValSpecialStatic;21719 result->special = ConstValSpecialStatic;
21211 result->type = type_info_pointer_type;21720 result->type = type_info_pointer_type;
2121221721
21213 ConstExprValue **fields = alloc_const_vals_ptrs(6);21722 ConstExprValue **fields = alloc_const_vals_ptrs(7);
21214 result->data.x_struct.fields = fields;21723 result->data.x_struct.fields = fields;
2121521724
21216 // size: Size21725 // size: Size
...@@ -21246,6 +21755,16 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty...@@ -21246,6 +21755,16 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
21246 fields[5]->special = ConstValSpecialStatic;21755 fields[5]->special = ConstValSpecialStatic;
21247 fields[5]->type = ira->codegen->builtin_types.entry_bool;21756 fields[5]->type = ira->codegen->builtin_types.entry_bool;
21248 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;21757 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
21250 return result;21769 return result;
21251};21770};
...@@ -21260,7 +21779,7 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,...@@ -21260,7 +21779,7 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
21260 inner_fields[1]->special = ConstValSpecialStatic;21779 inner_fields[1]->special = ConstValSpecialStatic;
21261 inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;21780 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;
21264 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true);21783 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true);
2126521784
21266 bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value);21785 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...@@ -21353,7 +21872,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21353 result->special = ConstValSpecialStatic;21872 result->special = ConstValSpecialStatic;
21354 result->type = ir_type_info_get_type(ira, "Array", nullptr);21873 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);
21357 result->data.x_struct.fields = fields;21876 result->data.x_struct.fields = fields;
2135821877
21359 // len: usize21878 // len: usize
...@@ -21366,7 +21885,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21366,7 +21885,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21366 fields[1]->special = ConstValSpecialStatic;21885 fields[1]->special = ConstValSpecialStatic;
21367 fields[1]->type = ira->codegen->builtin_types.entry_type;21886 fields[1]->type = ira->codegen->builtin_types.entry_type;
21368 fields[1]->data.x_type = type_entry->data.array.child_type;21887 fields[1]->data.x_type = type_entry->data.array.child_type;
2136921888 // 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;
21370 break;21892 break;
21371 }21893 }
21372 case ZigTypeIdVector: {21894 case ZigTypeIdVector: {
...@@ -21453,7 +21975,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr...@@ -21453,7 +21975,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2145321975
21454 ConstExprValue *enum_field_array = create_const_vals(1);21976 ConstExprValue *enum_field_array = create_const_vals(1);
21455 enum_field_array->special = ConstValSpecialStatic;21977 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);
21457 enum_field_array->data.x_array.special = ConstArraySpecialNone;21979 enum_field_array->data.x_array.special = ConstArraySpecialNone;
21458 enum_field_array->data.x_array.data.s_none.elements = create_const_vals(enum_field_count);21980 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...@@ -21501,7 +22023,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21501 uint32_t error_count = type_entry->data.error_set.err_count;22023 uint32_t error_count = type_entry->data.error_set.err_count;
21502 ConstExprValue *error_array = create_const_vals(1);22024 ConstExprValue *error_array = create_const_vals(1);
21503 error_array->special = ConstValSpecialStatic;22025 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);
21505 error_array->data.x_array.special = ConstArraySpecialNone;22027 error_array->data.x_array.special = ConstArraySpecialNone;
21506 error_array->data.x_array.data.s_none.elements = create_const_vals(error_count);22028 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...@@ -21521,7 +22043,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21521 if (error->cached_error_name_val != nullptr)22043 if (error->cached_error_name_val != nullptr)
21522 name = error->cached_error_name_val;22044 name = error->cached_error_name_val;
21523 if (name == nullptr)22045 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;
21525 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true);22047 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true);
21526 bigint_init_unsigned(&inner_fields[1]->data.x_bigint, error->value);22048 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...@@ -21597,7 +22119,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2159722119
21598 ConstExprValue *union_field_array = create_const_vals(1);22120 ConstExprValue *union_field_array = create_const_vals(1);
21599 union_field_array->special = ConstValSpecialStatic;22121 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);
21601 union_field_array->data.x_array.special = ConstArraySpecialNone;22123 union_field_array->data.x_array.special = ConstArraySpecialNone;
21602 union_field_array->data.x_array.data.s_none.elements = create_const_vals(union_field_count);22124 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...@@ -21627,7 +22149,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21627 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;22149 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
21628 inner_fields[2]->data.x_type = union_field->type_entry;22150 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;
21631 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);22153 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
2163222154
21633 union_field_val->data.x_struct.fields = inner_fields;22155 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...@@ -21677,7 +22199,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2167722199
21678 ConstExprValue *struct_field_array = create_const_vals(1);22200 ConstExprValue *struct_field_array = create_const_vals(1);
21679 struct_field_array->special = ConstValSpecialStatic;22201 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);
21681 struct_field_array->data.x_array.special = ConstArraySpecialNone;22203 struct_field_array->data.x_array.special = ConstArraySpecialNone;
21682 struct_field_array->data.x_array.data.s_none.elements = create_const_vals(struct_field_count);22204 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...@@ -21713,7 +22235,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
21713 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;22235 inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
21714 inner_fields[2]->data.x_type = struct_field->type_entry;22236 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;
21717 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);22239 init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
2171822240
21719 struct_field_val->data.x_struct.fields = inner_fields;22241 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...@@ -21780,7 +22302,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2178022302
21781 ConstExprValue *fn_arg_array = create_const_vals(1);22303 ConstExprValue *fn_arg_array = create_const_vals(1);
21782 fn_arg_array->special = ConstValSpecialStatic;22304 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);
21784 fn_arg_array->data.x_array.special = ConstArraySpecialNone;22306 fn_arg_array->data.x_array.special = ConstArraySpecialNone;
21785 fn_arg_array->data.x_array.data.s_none.elements = create_const_vals(fn_arg_count);22307 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...@@ -21878,6 +22400,20 @@ static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_va
21878 return struct_value->data.x_struct.fields[field_index];22400 return struct_value->data.x_struct.fields[field_index];
21879}22401}
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
21881static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)22417static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
21882{22418{
21883 ConstExprValue *value = get_const_field(ira, struct_value, name, field_index);22419 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...@@ -21900,6 +22436,7 @@ static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct
21900}22436}
2190122437
21902static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {22438static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {
22439 Error err;
21903 switch (tagTypeId) {22440 switch (tagTypeId) {
21904 case ZigTypeIdInvalid:22441 case ZigTypeIdInvalid:
21905 zig_unreachable();22442 zig_unreachable();
...@@ -21941,27 +22478,43 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi...@@ -21941,27 +22478,43 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
21941 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));22478 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
21942 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);22479 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
21943 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);22480 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
21944 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen,22481 ZigType *elem_type = get_const_field_meta_type(ira, payload, "child", 4);
21945 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,
21946 get_const_field_bool(ira, payload, "is_const", 1),22491 get_const_field_bool(ira, payload, "is_const", 1),
21947 get_const_field_bool(ira, payload, "is_volatile", 2),22492 get_const_field_bool(ira, payload, "is_volatile", 2),
21948 ptr_len,22493 ptr_len,
21949 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),22494 bigint_as_u32(get_const_field_lit_int(ira, payload, "alignment", 3)),
21950 0, // bit_offset_in_host22495 0, // bit_offset_in_host
21951 0, // host_int_bytes22496 0, // host_int_bytes
21952 get_const_field_bool(ira, payload, "is_allowzero", 5)22497 get_const_field_bool(ira, payload, "is_allowzero", 5),
21953 );22498 VECTOR_INDEX_NONE, nullptr, sentinel);
21954 if (size_enum_index != 2)22499 if (size_enum_index != 2)
21955 return ptr_type;22500 return ptr_type;
21956 return get_slice_type(ira->codegen, ptr_type);22501 return get_slice_type(ira->codegen, ptr_type);
21957 }22502 }
21958 case ZigTypeIdArray:22503 case ZigTypeIdArray: {
21959 assert(payload->special == ConstValSpecialStatic);22504 assert(payload->special == ConstValSpecialStatic);
21960 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));22505 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 }
21961 return get_array_type(ira->codegen,22513 return get_array_type(ira->codegen,
21962 get_const_field_meta_type(ira, payload, "child", 1),22514 elem_type,
21963 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0))22515 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),
21964 );22516 sentinel);
22517 }
21965 case ZigTypeIdComptimeFloat:22518 case ZigTypeIdComptimeFloat:
21966 return ira->codegen->builtin_types.entry_num_lit_float;22519 return ira->codegen->builtin_types.entry_num_lit_float;
21967 case ZigTypeIdComptimeInt:22520 case ZigTypeIdComptimeInt:
...@@ -22343,7 +22896,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru...@@ -22343,7 +22896,7 @@ static IrInstruction *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstru
22343 }22896 }
2234422897
22345 ZigType *result_type = get_array_type(ira->codegen,22898 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);
22347 IrInstruction *result = ir_const(ira, &instruction->base, result_type);22900 IrInstruction *result = ir_const(ira, &instruction->base, result_type);
22348 init_const_str_lit(ira->codegen, &result->value, file_contents);22901 init_const_str_lit(ira->codegen, &result->value, file_contents);
22349 return result;22902 return result;
...@@ -25566,6 +26119,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct...@@ -25566,6 +26119,12 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
25566 result->value.data.x_lazy = &lazy_ptr_type->base;26119 result->value.data.x_lazy = &lazy_ptr_type->base;
25567 lazy_ptr_type->base.id = LazyValueIdPtrType;26120 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
25569 lazy_ptr_type->elem_type = instruction->child_type->child;26128 lazy_ptr_type->elem_type = instruction->child_type->child;
25570 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)26129 if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr)
25571 return ira->codegen->invalid_instruction;26130 return ira->codegen->invalid_instruction;
...@@ -26487,7 +27046,7 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns...@@ -26487,7 +27046,7 @@ static IrInstruction *ir_analyze_instruction_implicit_cast(IrAnalyze *ira, IrIns
26487 ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child);27046 ZigType *dest_type = ir_resolve_type(ira, instruction->result_loc_cast->base.source_instruction->child);
26488 if (type_is_invalid(dest_type))27047 if (type_is_invalid(dest_type))
26489 return ira->codegen->invalid_instruction;27048 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);
26491}27050}
2649227051
26493static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) {27052static 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) {...@@ -27512,6 +28071,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27512 if (type_is_invalid(elem_type))28071 if (type_is_invalid(elem_type))
27513 return ErrorSemanticAnalyzeFail;28072 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
27515 uint32_t align_bytes = 0;28088 uint32_t align_bytes = 0;
27516 if (lazy_slice_type->align_inst != nullptr) {28089 if (lazy_slice_type->align_inst != nullptr) {
27517 if (!ir_resolve_align(ira, lazy_slice_type->align_inst, elem_type, &align_bytes))28090 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) {...@@ -27557,9 +28130,12 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27557 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;28130 ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown;
27558 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))28131 if ((err = type_resolve(ira->codegen, elem_type, needed_status)))
27559 return err;28132 return err;
27560 ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, elem_type,28133 ZigType *slice_ptr_type = get_pointer_to_type_extra2(ira->codegen, elem_type,
27561 lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes,28134 lazy_slice_type->is_const, lazy_slice_type->is_volatile,
27562 0, 0, lazy_slice_type->is_allowzero);28135 PtrLenUnknown,
28136 align_bytes,
28137 0, 0, lazy_slice_type->is_allowzero,
28138 VECTOR_INDEX_NONE, nullptr, sentinel_val);
27563 val->special = ConstValSpecialStatic;28139 val->special = ConstValSpecialStatic;
27564 assert(val->type->id == ZigTypeIdMetaType);28140 assert(val->type->id == ZigTypeIdMetaType);
27565 val->data.x_type = get_slice_type(ira->codegen, slice_ptr_type);28141 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) {...@@ -27573,6 +28149,20 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27573 if (type_is_invalid(elem_type))28149 if (type_is_invalid(elem_type))
27574 return ErrorSemanticAnalyzeFail;28150 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
27576 uint32_t align_bytes = 0;28166 uint32_t align_bytes = 0;
27577 if (lazy_ptr_type->align_inst != nullptr) {28167 if (lazy_ptr_type->align_inst != nullptr) {
27578 if (!ir_resolve_align(ira, lazy_ptr_type->align_inst, elem_type, &align_bytes))28168 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) {...@@ -27615,10 +28205,10 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
27615 }28205 }
27616 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;28206 bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
27617 assert(val->type->id == ZigTypeIdMetaType);28207 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,
27619 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,28209 lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes,
27620 lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes,28210 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);
27622 val->special = ConstValSpecialStatic;28212 val->special = ConstValSpecialStatic;
27623 return ErrorNone;28213 return ErrorNone;
27624 }28214 }
src/parser.cpp+118-65
...@@ -848,7 +848,12 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {...@@ -848,7 +848,12 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
848848
849 AstNode *type_expr = nullptr;849 AstNode *type_expr = nullptr;
850 if (eat_token_if(pc, TokenIdColon) != nullptr) {850 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 }
852 }857 }
853 AstNode *align_expr = ast_parse_byte_align(pc);858 AstNode *align_expr = ast_parse_byte_align(pc);
854 AstNode *expr = nullptr;859 AstNode *expr = nullptr;
...@@ -1718,7 +1723,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {...@@ -1718,7 +1723,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
1718 if (string_lit != nullptr) {1723 if (string_lit != nullptr) {
1719 AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);1724 AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);
1720 res->data.string_literal.buf = token_buf(string_lit);1725 res->data.string_literal.buf = token_buf(string_lit);
1721 res->data.string_literal.c = string_lit->data.str_lit.is_c_str;
1722 return res;1726 return res;
1723 }1727 }
17241728
...@@ -1834,8 +1838,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {...@@ -1834,8 +1838,10 @@ static AstNode *ast_parse_labeled_type_expr(ParseContext *pc) {
1834 return loop;1838 return loop;
1835 }1839 }
18361840
1837 if (label != nullptr)1841 if (label != nullptr) {
1838 ast_invalid_token_error(pc, peek_token(pc));1842 put_back_token(pc);
1843 put_back_token(pc);
1844 }
1839 return nullptr;1845 return nullptr;
1840}1846}
18411847
...@@ -1932,15 +1938,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {...@@ -1932,15 +1938,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) {
19321938
1933// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN1939// AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN
1934static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {1940static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1935 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);1941 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1936 if (sym_name == nullptr) {1942 return nullptr;
1937 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {1943
1938 return nullptr;1944 Token *sym_name = expect_token(pc, TokenIdSymbol);
1939 } else {1945 expect_token(pc, TokenIdRBracket);
1940 sym_name = expect_token(pc, TokenIdSymbol);
1941 expect_token(pc, TokenIdRBracket);
1942 }
1943 }
19441946
1945 Token *str = expect_token(pc, TokenIdStringLiteral);1947 Token *str = expect_token(pc, TokenIdStringLiteral);
1946 expect_token(pc, TokenIdLParen);1948 expect_token(pc, TokenIdLParen);
...@@ -1955,7 +1957,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {...@@ -1955,7 +1957,7 @@ static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) {
1955 expect_token(pc, TokenIdRParen);1957 expect_token(pc, TokenIdRParen);
19561958
1957 AsmOutput *res = allocate<AsmOutput>(1);1959 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);
1959 res->constraint = token_buf(str);1961 res->constraint = token_buf(str);
1960 res->variable_name = token_buf(var_name);1962 res->variable_name = token_buf(var_name);
1961 res->return_type = return_type;1963 res->return_type = return_type;
...@@ -1978,15 +1980,11 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {...@@ -1978,15 +1980,11 @@ static AstNode *ast_parse_asm_input(ParseContext *pc) {
19781980
1979// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN1981// AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN
1980static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {1982static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1981 Token *sym_name = eat_token_if(pc, TokenIdBracketUnderscoreBracket);1983 if (eat_token_if(pc, TokenIdLBracket) == nullptr)
1982 if (sym_name == nullptr) {1984 return nullptr;
1983 if (eat_token_if(pc, TokenIdLBracket) == nullptr) {1985
1984 return nullptr;1986 Token *sym_name = expect_token(pc, TokenIdSymbol);
1985 } else {1987 expect_token(pc, TokenIdRBracket);
1986 sym_name = expect_token(pc, TokenIdSymbol);
1987 expect_token(pc, TokenIdRBracket);
1988 }
1989 }
19901988
1991 Token *constraint = expect_token(pc, TokenIdStringLiteral);1989 Token *constraint = expect_token(pc, TokenIdStringLiteral);
1992 expect_token(pc, TokenIdLParen);1990 expect_token(pc, TokenIdLParen);
...@@ -1994,7 +1992,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {...@@ -1994,7 +1992,7 @@ static AsmInput *ast_parse_asm_input_item(ParseContext *pc) {
1994 expect_token(pc, TokenIdRParen);1992 expect_token(pc, TokenIdRParen);
19951993
1996 AsmInput *res = allocate<AsmInput>(1);1994 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);
1998 res->constraint = token_buf(constraint);1996 res->constraint = token_buf(constraint);
1999 res->expr = expr;1997 res->expr = expr;
2000 return res;1998 return res;
...@@ -2614,37 +2612,28 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2614,37 +2612,28 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2614 put_back_token(pc);2612 put_back_token(pc);
2615 }2613 }
26162614
2617 AstNode *array = ast_parse_array_type_start(pc);2615 Token *arr_init_lbracket = eat_token_if(pc, TokenIdLBracket);
2618 if (array != nullptr) {2616 if (arr_init_lbracket != nullptr) {
2619 assert(array->type == NodeTypeArrayType);2617 Token *underscore = eat_token_if(pc, TokenIdSymbol);
2620 while (true) {2618 if (underscore == nullptr) {
2621 Token *allowzero_token = eat_token_if(pc, TokenIdKeywordAllowZero);2619 put_back_token(pc);
2622 if (allowzero_token != nullptr) {2620 } else if (!buf_eql_str(token_buf(underscore), "_")) {
2623 array->data.array_type.allow_zero_token = allowzero_token;2621 put_back_token(pc);
2624 continue;2622 put_back_token(pc);
2625 }2623 } else {
26262624 AstNode *sentinel = nullptr;
2627 AstNode *align_expr = ast_parse_byte_align(pc);2625 Token *colon = eat_token_if(pc, TokenIdColon);
2628 if (align_expr != nullptr) {2626 if (colon != nullptr) {
2629 array->data.array_type.align_expr = align_expr;2627 sentinel = ast_expect(pc, ast_parse_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;
2641 }2628 }
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;
2643 }2633 }
2644
2645 return array;
2646 }2634 }
26472635
2636
2648 AstNode *ptr = ast_parse_ptr_type_start(pc);2637 AstNode *ptr = ast_parse_ptr_type_start(pc);
2649 if (ptr != nullptr) {2638 if (ptr != nullptr) {
2650 assert(ptr->type == NodeTypePointerType);2639 assert(ptr->type == NodeTypePointerType);
...@@ -2690,9 +2679,35 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {...@@ -2690,9 +2679,35 @@ static AstNode *ast_parse_prefix_type_op(ParseContext *pc) {
2690 return ptr;2679 return ptr;
2691 }2680 }
26922681
2693 Token *arr_init = eat_token_if(pc, TokenIdBracketUnderscoreBracket);2682 AstNode *array = ast_parse_array_type_start(pc);
2694 if (arr_init != nullptr) {2683 if (array != nullptr) {
2695 return ast_create_node(pc, NodeTypeInferredArrayType, arr_init);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;
2696 }2711 }
26972712
26982713
...@@ -2766,9 +2781,15 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2766,9 +2781,15 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2766 return nullptr;2781 return nullptr;
27672782
2768 AstNode *size = ast_parse_expr(pc);2783 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 }
2769 expect_token(pc, TokenIdRBracket);2789 expect_token(pc, TokenIdRBracket);
2770 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);2790 AstNode *res = ast_create_node(pc, NodeTypeArrayType, lbracket);
2771 res->data.array_type.size = size;2791 res->data.array_type.size = size;
2792 res->data.array_type.sentinel = sentinel;
2772 return res;2793 return res;
2773}2794}
27742795
...@@ -2778,35 +2799,63 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {...@@ -2778,35 +2799,63 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
2778// / PTRUNKNOWN2799// / PTRUNKNOWN
2779// / PTRC2800// / PTRC
2780static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {2801static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
2802 AstNode *sentinel = nullptr;
2803
2781 Token *asterisk = eat_token_if(pc, TokenIdStar);2804 Token *asterisk = eat_token_if(pc, TokenIdStar);
2782 if (asterisk != nullptr) {2805 if (asterisk != nullptr) {
2806 Token *colon = eat_token_if(pc, TokenIdColon);
2807 if (colon != nullptr) {
2808 sentinel = ast_expect(pc, ast_parse_expr);
2809 }
2783 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);2810 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk);
2784 res->data.pointer_type.star_token = asterisk;2811 res->data.pointer_type.star_token = asterisk;
2812 res->data.pointer_type.sentinel = sentinel;
2785 return res;2813 return res;
2786 }2814 }
27872815
2788 Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);2816 Token *asterisk2 = eat_token_if(pc, TokenIdStarStar);
2789 if (asterisk2 != nullptr) {2817 if (asterisk2 != nullptr) {
2818 Token *colon = eat_token_if(pc, TokenIdColon);
2819 if (colon != nullptr) {
2820 sentinel = ast_expect(pc, ast_parse_expr);
2821 }
2790 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);2822 AstNode *res = ast_create_node(pc, NodeTypePointerType, asterisk2);
2791 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);2823 AstNode *res2 = ast_create_node(pc, NodeTypePointerType, asterisk2);
2792 res->data.pointer_type.star_token = asterisk2;2824 res->data.pointer_type.star_token = asterisk2;
2793 res2->data.pointer_type.star_token = asterisk2;2825 res2->data.pointer_type.star_token = asterisk2;
2826 res2->data.pointer_type.sentinel = sentinel;
2794 res->data.pointer_type.op_expr = res2;2827 res->data.pointer_type.op_expr = res2;
2795 return res;2828 return res;
2796 }2829 }
27972830
2798 Token *multptr = eat_token_if(pc, TokenIdBracketStarBracket);2831 Token *lbracket = eat_token_if(pc, TokenIdLBracket);
2799 if (multptr != nullptr) {2832 if (lbracket != nullptr) {
2800 AstNode *res = ast_create_node(pc, NodeTypePointerType, multptr);2833 Token *star = eat_token_if(pc, TokenIdStar);
2801 res->data.pointer_type.star_token = multptr;2834 if (star == nullptr) {
2802 return res;2835 put_back_token(pc);
2803 }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);2849 Token *colon = eat_token_if(pc, TokenIdColon);
2806 if (cptr != nullptr) {2850 if (colon != nullptr) {
2807 AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);2851 sentinel = ast_expect(pc, ast_parse_expr);
2808 res->data.pointer_type.star_token = cptr;2852 }
2809 return res;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 }
2810 }2859 }
28112860
2812 return nullptr;2861 return nullptr;
...@@ -3084,10 +3133,12 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3084,10 +3133,12 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3084 break;3133 break;
3085 case NodeTypeArrayType:3134 case NodeTypeArrayType:
3086 visit_field(&node->data.array_type.size, visit, context);3135 visit_field(&node->data.array_type.size, visit, context);
3136 visit_field(&node->data.array_type.sentinel, visit, context);
3087 visit_field(&node->data.array_type.child_type, visit, context);3137 visit_field(&node->data.array_type.child_type, visit, context);
3088 visit_field(&node->data.array_type.align_expr, visit, context);3138 visit_field(&node->data.array_type.align_expr, visit, context);
3089 break;3139 break;
3090 case NodeTypeInferredArrayType:3140 case NodeTypeInferredArrayType:
3141 visit_field(&node->data.array_type.sentinel, visit, context);
3091 visit_field(&node->data.array_type.child_type, visit, context);3142 visit_field(&node->data.array_type.child_type, visit, context);
3092 break;3143 break;
3093 case NodeTypeAnyFrameType:3144 case NodeTypeAnyFrameType:
...@@ -3097,6 +3148,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3097,6 +3148,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3097 // none3148 // none
3098 break;3149 break;
3099 case NodeTypePointerType:3150 case NodeTypePointerType:
3151 visit_field(&node->data.pointer_type.sentinel, visit, context);
3100 visit_field(&node->data.pointer_type.align_expr, visit, context);3152 visit_field(&node->data.pointer_type.align_expr, visit, context);
3101 visit_field(&node->data.pointer_type.op_expr, visit, context);3153 visit_field(&node->data.pointer_type.op_expr, visit, context);
3102 break;3154 break;
...@@ -3116,6 +3168,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont...@@ -3116,6 +3168,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
3116 visit_field(&node->data.suspend.block, visit, context);3168 visit_field(&node->data.suspend.block, visit, context);
3117 break;3169 break;
3118 case NodeTypeEnumLiteral:3170 case NodeTypeEnumLiteral:
3171 case NodeTypeVarFieldType:
3119 break;3172 break;
3120 }3173 }
3121}3174}
src/tokenizer.cpp+4-118
...@@ -33,10 +33,10 @@...@@ -33,10 +33,10 @@
33 '0': \33 '0': \
34 case DIGIT_NON_ZERO34 case DIGIT_NON_ZERO
3535
36#define ALPHA_EXCEPT_C \36#define ALPHA \
37 'a': \37 'a': \
38 case 'b': \38 case 'b': \
39 /*case 'c':*/ \39 case 'c': \
40 case 'd': \40 case 'd': \
41 case 'e': \41 case 'e': \
42 case 'f': \42 case 'f': \
...@@ -87,10 +87,6 @@...@@ -87,10 +87,6 @@
87 case 'Y': \87 case 'Y': \
88 case 'Z'88 case 'Z'
8989
90#define ALPHA \
91 ALPHA_EXCEPT_C: \
92 case 'c'
93
94#define SYMBOL_CHAR \90#define SYMBOL_CHAR \
95 ALPHA: \91 ALPHA: \
96 case DIGIT: \92 case DIGIT: \
...@@ -180,7 +176,6 @@ static bool is_symbol_char(uint8_t c) {...@@ -180,7 +176,6 @@ static bool is_symbol_char(uint8_t c) {
180enum TokenizeState {176enum TokenizeState {
181 TokenizeStateStart,177 TokenizeStateStart,
182 TokenizeStateSymbol,178 TokenizeStateSymbol,
183 TokenizeStateSymbolFirstC,
184 TokenizeStateZero, // "0", which might lead to "0x"179 TokenizeStateZero, // "0", which might lead to "0x"
185 TokenizeStateNumber, // "123", "0x123"180 TokenizeStateNumber, // "123", "0x123"
186 TokenizeStateNumberDot,181 TokenizeStateNumberDot,
...@@ -227,10 +222,6 @@ enum TokenizeState {...@@ -227,10 +222,6 @@ enum TokenizeState {
227 TokenizeStateSawAtSign,222 TokenizeStateSawAtSign,
228 TokenizeStateCharCode,223 TokenizeStateCharCode,
229 TokenizeStateError,224 TokenizeStateError,
230 TokenizeStateLBracket,
231 TokenizeStateLBracketStar,
232 TokenizeStateLBracketStarC,
233 TokenizeStateLBracketUnderscore,
234};225};
235226
236227
...@@ -279,7 +270,6 @@ static void set_token_id(Tokenize *t, Token *token, TokenId id) {...@@ -279,7 +270,6 @@ static void set_token_id(Tokenize *t, Token *token, TokenId id) {
279 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {270 } else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {
280 memset(&token->data.str_lit.str, 0, sizeof(Buf));271 memset(&token->data.str_lit.str, 0, sizeof(Buf));
281 buf_resize(&token->data.str_lit.str, 0);272 buf_resize(&token->data.str_lit.str, 0);
282 token->data.str_lit.is_c_str = false;
283 }273 }
284}274}
285275
...@@ -429,12 +419,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -429,12 +419,7 @@ void tokenize(Buf *buf, Tokenization *out) {
429 switch (c) {419 switch (c) {
430 case WHITESPACE:420 case WHITESPACE:
431 break;421 break;
432 case 'c':422 case ALPHA:
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:
438 case '_':423 case '_':
439 t.state = TokenizeStateSymbol;424 t.state = TokenizeStateSymbol;
440 begin_token(&t, TokenIdSymbol);425 begin_token(&t, TokenIdSymbol);
...@@ -491,8 +476,8 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -491,8 +476,8 @@ void tokenize(Buf *buf, Tokenization *out) {
491 end_token(&t);476 end_token(&t);
492 break;477 break;
493 case '[':478 case '[':
494 t.state = TokenizeStateLBracket;
495 begin_token(&t, TokenIdLBracket);479 begin_token(&t, TokenIdLBracket);
480 end_token(&t);
496 break;481 break;
497 case ']':482 case ']':
498 begin_token(&t, TokenIdRBracket);483 begin_token(&t, TokenIdRBracket);
...@@ -786,62 +771,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -786,62 +771,6 @@ void tokenize(Buf *buf, Tokenization *out) {
786 continue;771 continue;
787 }772 }
788 break;773 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;
845 case TokenizeStateSawPlusPercent:774 case TokenizeStateSawPlusPercent:
846 switch (c) {775 switch (c) {
847 case '=':776 case '=':
...@@ -1007,19 +936,7 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1007,19 +936,7 @@ void tokenize(Buf *buf, Tokenization *out) {
1007 switch (c) {936 switch (c) {
1008 case WHITESPACE:937 case WHITESPACE:
1009 break;938 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;
1019 case '\\':939 case '\\':
1020 if (t.cur_tok->data.str_lit.is_c_str) {
1021 invalid_char_error(&t, c);
1022 }
1023 t.state = TokenizeStateLineStringContinue;940 t.state = TokenizeStateLineStringContinue;
1024 break;941 break;
1025 default:942 default:
...@@ -1084,29 +1001,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1084,29 +1001,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1084 break;1001 break;
1085 }1002 }
1086 break;1003 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;
1110 case TokenizeStateSawAtSign:1004 case TokenizeStateSawAtSign:
1111 switch (c) {1005 switch (c) {
1112 case '"':1006 case '"':
...@@ -1544,7 +1438,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1544,7 +1438,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1544 tokenize_error(&t, "unterminated character literal");1438 tokenize_error(&t, "unterminated character literal");
1545 break;1439 break;
1546 case TokenizeStateSymbol:1440 case TokenizeStateSymbol:
1547 case TokenizeStateSymbolFirstC:
1548 case TokenizeStateZero:1441 case TokenizeStateZero:
1549 case TokenizeStateNumber:1442 case TokenizeStateNumber:
1550 case TokenizeStateFloatFraction:1443 case TokenizeStateFloatFraction:
...@@ -1572,7 +1465,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1572,7 +1465,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1572 case TokenizeStateLineString:1465 case TokenizeStateLineString:
1573 case TokenizeStateLineStringEnd:1466 case TokenizeStateLineStringEnd:
1574 case TokenizeStateSawBarBar:1467 case TokenizeStateSawBarBar:
1575 case TokenizeStateLBracket:
1576 case TokenizeStateDocComment:1468 case TokenizeStateDocComment:
1577 case TokenizeStateContainerDocComment:1469 case TokenizeStateContainerDocComment:
1578 end_token(&t);1470 end_token(&t);
...@@ -1581,9 +1473,6 @@ void tokenize(Buf *buf, Tokenization *out) {...@@ -1581,9 +1473,6 @@ void tokenize(Buf *buf, Tokenization *out) {
1581 case TokenizeStateSawBackslash:1473 case TokenizeStateSawBackslash:
1582 case TokenizeStateLineStringContinue:1474 case TokenizeStateLineStringContinue:
1583 case TokenizeStateLineStringContinueC:1475 case TokenizeStateLineStringContinueC:
1584 case TokenizeStateLBracketStar:
1585 case TokenizeStateLBracketStarC:
1586 case TokenizeStateLBracketUnderscore:
1587 tokenize_error(&t, "unexpected EOF");1476 tokenize_error(&t, "unexpected EOF");
1588 break;1477 break;
1589 case TokenizeStateLineComment:1478 case TokenizeStateLineComment:
...@@ -1623,8 +1512,6 @@ const char * token_name(TokenId id) {...@@ -1623,8 +1512,6 @@ const char * token_name(TokenId id) {
1623 case TokenIdBitShiftRight: return ">>";1512 case TokenIdBitShiftRight: return ">>";
1624 case TokenIdBitShiftRightEq: return ">>=";1513 case TokenIdBitShiftRightEq: return ">>=";
1625 case TokenIdBitXorEq: return "^=";1514 case TokenIdBitXorEq: return "^=";
1626 case TokenIdBracketStarBracket: return "[*]";
1627 case TokenIdBracketStarCBracket: return "[*c]";
1628 case TokenIdCharLiteral: return "CharLiteral";1515 case TokenIdCharLiteral: return "CharLiteral";
1629 case TokenIdCmpEq: return "==";1516 case TokenIdCmpEq: return "==";
1630 case TokenIdCmpGreaterOrEq: return ">=";1517 case TokenIdCmpGreaterOrEq: return ">=";
...@@ -1728,7 +1615,6 @@ const char * token_name(TokenId id) {...@@ -1728,7 +1615,6 @@ const char * token_name(TokenId id) {
1728 case TokenIdTimesPercent: return "*%";1615 case TokenIdTimesPercent: return "*%";
1729 case TokenIdTimesPercentEq: return "*%=";1616 case TokenIdTimesPercentEq: return "*%=";
1730 case TokenIdBarBarEq: return "||=";1617 case TokenIdBarBarEq: return "||=";
1731 case TokenIdBracketUnderscoreBracket: return "[_]";
1732 case TokenIdCount:1618 case TokenIdCount:
1733 zig_unreachable();1619 zig_unreachable();
1734 }1620 }
src/tokenizer.hpp-4
...@@ -28,9 +28,6 @@ enum TokenId {...@@ -28,9 +28,6 @@ enum TokenId {
28 TokenIdBitShiftRight,28 TokenIdBitShiftRight,
29 TokenIdBitShiftRightEq,29 TokenIdBitShiftRightEq,
30 TokenIdBitXorEq,30 TokenIdBitXorEq,
31 TokenIdBracketStarBracket,
32 TokenIdBracketStarCBracket,
33 TokenIdBracketUnderscoreBracket,
34 TokenIdCharLiteral,31 TokenIdCharLiteral,
35 TokenIdCmpEq,32 TokenIdCmpEq,
36 TokenIdCmpGreaterOrEq,33 TokenIdCmpGreaterOrEq,
...@@ -149,7 +146,6 @@ struct TokenIntLit {...@@ -149,7 +146,6 @@ struct TokenIntLit {
149146
150struct TokenStrLit {147struct TokenStrLit {
151 Buf str;148 Buf str;
152 bool is_c_str;
153};149};
154150
155struct TokenCharLit {151struct TokenCharLit {
src/translate_c.cpp+7-15
...@@ -291,9 +291,9 @@ static TokenId ptr_len_to_token_id(PtrLen ptr_len) {...@@ -291,9 +291,9 @@ static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
291 case PtrLenSingle:291 case PtrLenSingle:
292 return TokenIdStar;292 return TokenIdStar;
293 case PtrLenUnknown:293 case PtrLenUnknown:
294 return TokenIdBracketStarBracket;294 return TokenIdLBracket;
295 case PtrLenC:295 case PtrLenC:
296 return TokenIdBracketStarCBracket;296 return TokenIdSymbol;
297 }297 }
298 zig_unreachable();298 zig_unreachable();
299}299}
...@@ -321,17 +321,9 @@ static AstNode *trans_create_node_bool(Context *c, bool value) {...@@ -321,17 +321,9 @@ static AstNode *trans_create_node_bool(Context *c, bool value) {
321 return bool_node;321 return bool_node;
322}322}
323323
324static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {324static AstNode *trans_create_node_str_lit(Context *c, Buf *buf) {
325 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);325 AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
326 node->data.string_literal.buf = buf;326 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;
335 return node;327 return node;
336}328}
337329
...@@ -630,7 +622,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,...@@ -630,7 +622,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
630// zig_type_node622// zig_type_node
631623
632 AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");624 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")));
634 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");626 AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
635 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");627 AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
636 AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);628 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...@@ -3389,7 +3381,7 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc
3389 case ZigClangStringLiteral_StringKind_UTF8: {3381 case ZigClangStringLiteral_StringKind_UTF8: {
3390 size_t str_len;3382 size_t str_len;
3391 const char *str_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &str_len);3383 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));
3393 return maybe_suppress_result(c, result_used, node);3385 return maybe_suppress_result(c, result_used, node);
3394 }3386 }
3395 case ZigClangStringLiteral_StringKind_UTF16:3387 case ZigClangStringLiteral_StringKind_UTF16:
...@@ -4888,7 +4880,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok...@@ -4888,7 +4880,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
4888 return trans_create_node_unsigned(c, tok->data.char_lit);4880 return trans_create_node_unsigned(c, tok->data.char_lit);
4889 case CTokIdStrLit:4881 case CTokIdStrLit:
4890 *tok_i += 1;4882 *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));
4892 case CTokIdMinus:4884 case CTokIdMinus:
4893 *tok_i += 1;4885 *tok_i += 1;
4894 return parse_ctok_num_lit(c, ctok, tok_i, true);4886 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...@@ -4935,7 +4927,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
4935 // (dest)(x)4927 // (dest)(x)
49364928
4937 AstNode *import_builtin = trans_create_node_builtin_fn_call_str(c, "import");4929 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")));
4939 AstNode *typeid_type = trans_create_node_field_access_str(c, import_builtin, "TypeId");4931 AstNode *typeid_type = trans_create_node_field_access_str(c, import_builtin, "TypeId");
4940 AstNode *typeid_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");4932 AstNode *typeid_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");
4941 AstNode *typeid_integer = trans_create_node_field_access_str(c, typeid_type, "Int");4933 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 {...@@ -87,7 +87,7 @@ fn exec(cwd: []const u8, argv: []const []const u8) !ChildProcess.ExecResult {
87fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {87fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void {
88 _ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });88 _ = try exec(dir_path, [_][]const u8{ zig_exe, "init-lib" });
89 const test_result = try exec(dir_path, [_][]const u8{ zig_exe, "build", "test" });89 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"));
91}91}
9292
93fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void {93fn 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 {...@@ -7,7 +7,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
7 cases.addC("hello world with libc",7 cases.addC("hello world with libc",
8 \\const c = @cImport(@cInclude("stdio.h"));8 \\const c = @cImport(@cInclude("stdio.h"));
9 \\export fn main(argc: c_int, argv: [*][*]u8) c_int {9 \\export fn main(argc: c_int, argv: [*][*]u8) c_int {
10 \\ _ = c.puts(c"Hello, world!");10 \\ _ = c.puts("Hello, world!");
11 \\ return 0;11 \\ return 0;
12 \\}12 \\}
13 , "Hello, world!" ++ std.cstr.line_sep);13 , "Hello, world!" ++ std.cstr.line_sep);
...@@ -144,75 +144,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -144,75 +144,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
144 \\ // we want actual \n, not \r\n144 \\ // we want actual \n, not \r\n
145 \\ _ = c._setmode(1, c._O_BINARY);145 \\ _ = c._setmode(1, c._O_BINARY);
146 \\ }146 \\ }
147 \\ _ = c.printf(c"0: %llu\n",147 \\ _ = c.printf("0: %llu\n",
148 \\ @as(u64, 0));148 \\ @as(u64, 0));
149 \\ _ = c.printf(c"320402575052271: %llu\n",149 \\ _ = c.printf("320402575052271: %llu\n",
150 \\ @as(u64, 320402575052271));150 \\ @as(u64, 320402575052271));
151 \\ _ = c.printf(c"0x01236789abcdef: %llu\n",151 \\ _ = c.printf("0x01236789abcdef: %llu\n",
152 \\ @as(u64, 0x01236789abcdef));152 \\ @as(u64, 0x01236789abcdef));
153 \\ _ = c.printf(c"0xffffffffffffffff: %llu\n",153 \\ _ = c.printf("0xffffffffffffffff: %llu\n",
154 \\ @as(u64, 0xffffffffffffffff));154 \\ @as(u64, 0xffffffffffffffff));
155 \\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n",155 \\ _ = c.printf("0x000000ffffffffffffffff: %llu\n",
156 \\ @as(u64, 0x000000ffffffffffffffff));156 \\ @as(u64, 0x000000ffffffffffffffff));
157 \\ _ = c.printf(c"0o1777777777777777777777: %llu\n",157 \\ _ = c.printf("0o1777777777777777777777: %llu\n",
158 \\ @as(u64, 0o1777777777777777777777));158 \\ @as(u64, 0o1777777777777777777777));
159 \\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n",159 \\ _ = c.printf("0o0000001777777777777777777777: %llu\n",
160 \\ @as(u64, 0o0000001777777777777777777777));160 \\ @as(u64, 0o0000001777777777777777777777));
161 \\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",161 \\ _ = c.printf("0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
162 \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111));162 \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111));
163 \\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",163 \\ _ = c.printf("0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
164 \\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111));164 \\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111));
165 \\165 \\
166 \\ _ = c.printf(c"\n");166 \\ _ = c.printf("\n");
167 \\167 \\
168 \\ _ = c.printf(c"0.0: %.013a\n",168 \\ _ = c.printf("0.0: %.013a\n",
169 \\ @as(f64, 0.0));169 \\ @as(f64, 0.0));
170 \\ _ = c.printf(c"0e0: %.013a\n",170 \\ _ = c.printf("0e0: %.013a\n",
171 \\ @as(f64, 0e0));171 \\ @as(f64, 0e0));
172 \\ _ = c.printf(c"0.0e0: %.013a\n",172 \\ _ = c.printf("0.0e0: %.013a\n",
173 \\ @as(f64, 0.0e0));173 \\ @as(f64, 0.0e0));
174 \\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",174 \\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
175 \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));175 \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));
176 \\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",176 \\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
177 \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));177 \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));
178 \\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",178 \\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
179 \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000));179 \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000));
180 \\ _ = c.printf(c"1.0: %.013a\n",180 \\ _ = c.printf("1.0: %.013a\n",
181 \\ @as(f64, 1.0));181 \\ @as(f64, 1.0));
182 \\ _ = c.printf(c"10.0: %.013a\n",182 \\ _ = c.printf("10.0: %.013a\n",
183 \\ @as(f64, 10.0));183 \\ @as(f64, 10.0));
184 \\ _ = c.printf(c"10.5: %.013a\n",184 \\ _ = c.printf("10.5: %.013a\n",
185 \\ @as(f64, 10.5));185 \\ @as(f64, 10.5));
186 \\ _ = c.printf(c"10.5e5: %.013a\n",186 \\ _ = c.printf("10.5e5: %.013a\n",
187 \\ @as(f64, 10.5e5));187 \\ @as(f64, 10.5e5));
188 \\ _ = c.printf(c"10.5e+5: %.013a\n",188 \\ _ = c.printf("10.5e+5: %.013a\n",
189 \\ @as(f64, 10.5e+5));189 \\ @as(f64, 10.5e+5));
190 \\ _ = c.printf(c"50.0e-2: %.013a\n",190 \\ _ = c.printf("50.0e-2: %.013a\n",
191 \\ @as(f64, 50.0e-2));191 \\ @as(f64, 50.0e-2));
192 \\ _ = c.printf(c"50e-2: %.013a\n",192 \\ _ = c.printf("50e-2: %.013a\n",
193 \\ @as(f64, 50e-2));193 \\ @as(f64, 50e-2));
194 \\194 \\
195 \\ _ = c.printf(c"\n");195 \\ _ = c.printf("\n");
196 \\196 \\
197 \\ _ = c.printf(c"0x1.0: %.013a\n",197 \\ _ = c.printf("0x1.0: %.013a\n",
198 \\ @as(f64, 0x1.0));198 \\ @as(f64, 0x1.0));
199 \\ _ = c.printf(c"0x10.0: %.013a\n",199 \\ _ = c.printf("0x10.0: %.013a\n",
200 \\ @as(f64, 0x10.0));200 \\ @as(f64, 0x10.0));
201 \\ _ = c.printf(c"0x100.0: %.013a\n",201 \\ _ = c.printf("0x100.0: %.013a\n",
202 \\ @as(f64, 0x100.0));202 \\ @as(f64, 0x100.0));
203 \\ _ = c.printf(c"0x103.0: %.013a\n",203 \\ _ = c.printf("0x103.0: %.013a\n",
204 \\ @as(f64, 0x103.0));204 \\ @as(f64, 0x103.0));
205 \\ _ = c.printf(c"0x103.7: %.013a\n",205 \\ _ = c.printf("0x103.7: %.013a\n",
206 \\ @as(f64, 0x103.7));206 \\ @as(f64, 0x103.7));
207 \\ _ = c.printf(c"0x103.70: %.013a\n",207 \\ _ = c.printf("0x103.70: %.013a\n",
208 \\ @as(f64, 0x103.70));208 \\ @as(f64, 0x103.70));
209 \\ _ = c.printf(c"0x103.70p4: %.013a\n",209 \\ _ = c.printf("0x103.70p4: %.013a\n",
210 \\ @as(f64, 0x103.70p4));210 \\ @as(f64, 0x103.70p4));
211 \\ _ = c.printf(c"0x103.70p5: %.013a\n",211 \\ _ = c.printf("0x103.70p5: %.013a\n",
212 \\ @as(f64, 0x103.70p5));212 \\ @as(f64, 0x103.70p5));
213 \\ _ = c.printf(c"0x103.70p+5: %.013a\n",213 \\ _ = c.printf("0x103.70p+5: %.013a\n",
214 \\ @as(f64, 0x103.70p+5));214 \\ @as(f64, 0x103.70p+5));
215 \\ _ = c.printf(c"0x103.70p-5: %.013a\n",215 \\ _ = c.printf("0x103.70p-5: %.013a\n",
216 \\ @as(f64, 0x103.70p-5));216 \\ @as(f64, 0x103.70p-5));
217 \\217 \\
218 \\ return 0;218 \\ return 0;
...@@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
323 \\ const x: f64 = small;323 \\ const x: f64 = small;
324 \\ const y = @floatToInt(i32, x);324 \\ const y = @floatToInt(i32, x);
325 \\ const z = @intToFloat(f64, y);325 \\ 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));
327 \\ return 0;327 \\ return 0;
328 \\}328 \\}
329 , "3.25\n3\n3.00\n-0.40\n");329 , "3.25\n3\n3.00\n-0.40\n");
test/compile_errors.zig+58-17
...@@ -2,6 +2,33 @@ const tests = @import("tests.zig");...@@ -2,6 +2,33 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub 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
5 cases.add(32 cases.add(
6 "empty switch on an integer",33 "empty switch on an integer",
7 \\export fn entry() void {34 \\export fn entry() void {
...@@ -99,6 +126,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -99,6 +126,18 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
99 "tmp.zig:9:27: error: @atomicRmw on enum only works with .Xchg",126 "tmp.zig:9:27: error: @atomicRmw on enum only works with .Xchg",
100 );127 );
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
102 cases.add(141 cases.add(
103 "atomic orderings of atomicStore Acquire or AcqRel",142 "atomic orderings of atomicStore Acquire or AcqRel",
104 \\export fn entry() void {143 \\export fn entry() void {
...@@ -183,7 +222,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -183,7 +222,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
183 cases.add(222 cases.add(
184 "using an unknown len ptr type instead of array",223 "using an unknown len ptr type instead of array",
185 \\const resolutions = [*][*]const u8{224 \\const resolutions = [*][*]const u8{
186 \\ c"[320 240 ]",225 \\ "[320 240 ]",
187 \\ null,226 \\ null,
188 \\};227 \\};
189 \\comptime {228 \\comptime {
...@@ -800,10 +839,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -800,10 +839,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
800 "peer cast then implicit cast const pointer to mutable C pointer",839 "peer cast then implicit cast const pointer to mutable C pointer",
801 \\export fn func() void {840 \\export fn func() void {
802 \\ var strValue: [*c]u8 = undefined;841 \\ var strValue: [*c]u8 = undefined;
803 \\ strValue = strValue orelse c"";842 \\ strValue = strValue orelse "";
804 \\}843 \\}
805 ,844 ,
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",
807 );847 );
808848
809 cases.add(849 cases.add(
...@@ -1134,7 +1174,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1134,7 +1174,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1134 "libc headers note",1174 "libc headers note",
1135 \\const c = @cImport(@cInclude("stdio.h"));1175 \\const c = @cImport(@cInclude("stdio.h"));
1136 \\export fn entry() void {1176 \\export fn entry() void {
1137 \\ _ = c.printf(c"hello, world!\n");1177 \\ _ = c.printf("hello, world!\n");
1138 \\}1178 \\}
1139 ,1179 ,
1140 "tmp.zig:1:11: error: C import failed",1180 "tmp.zig:1:11: error: C import failed",
...@@ -1342,7 +1382,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1342,7 +1382,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1342 \\ ptr_opt_many_ptr = c_ptr;1382 \\ ptr_opt_many_ptr = c_ptr;
1343 \\}1383 \\}
1344 \\export fn entry2() void {1384 \\export fn entry2() void {
1345 \\ var buf: [4]u8 = "aoeu";1385 \\ var buf: [4]u8 = "aoeu".*;
1346 \\ var slice: []u8 = &buf;1386 \\ var slice: []u8 = &buf;
1347 \\ var opt_many_ptr: [*]u8 = slice.ptr;1387 \\ var opt_many_ptr: [*]u8 = slice.ptr;
1348 \\ var ptr_opt_many_ptr = &opt_many_ptr;1388 \\ var ptr_opt_many_ptr = &opt_many_ptr;
...@@ -1537,7 +1577,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1537,7 +1577,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1537 cases.add(1577 cases.add(
1538 "reading past end of pointer casted array",1578 "reading past end of pointer casted array",
1539 \\comptime {1579 \\comptime {
1540 \\ const array = "aoeu";1580 \\ const array: [4]u8 = "aoeu".*;
1541 \\ const slice = array[1..];1581 \\ const slice = array[1..];
1542 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);1582 \\ const int_ptr = @ptrCast(*const u24, slice.ptr);
1543 \\ const deref = int_ptr.*;1583 \\ const deref = int_ptr.*;
...@@ -2460,12 +2500,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2460,12 +2500,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2460 );2500 );
24612501
2462 cases.add(2502 cases.add(
2463 "var not allowed in structs",2503 "var makes structs required to be comptime known",
2464 \\export fn entry() void {2504 \\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)};
2466 \\}2507 \\}
2467 ,2508 ,
2468 "tmp.zig:2:23: error: invalid token: 'var'",2509 "tmp.zig:3:4: error: variable of type 'S' must be const or comptime",
2469 );2510 );
24702511
2471 cases.add(2512 cases.add(
...@@ -3371,11 +3412,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3371,11 +3412,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3371 cases.add(3412 cases.add(
3372 "variable has wrong type",3413 "variable has wrong type",
3373 \\export fn f() i32 {3414 \\export fn f() i32 {
3374 \\ const a = c"a";3415 \\ const a = "a";
3375 \\ return a;3416 \\ return a;
3376 \\}3417 \\}
3377 ,3418 ,
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'",
3379 );3420 );
33803421
3381 cases.add(3422 cases.add(
...@@ -3846,12 +3887,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3846,12 +3887,12 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3846 cases.add(3887 cases.add(
3847 "array concatenation with wrong type",3888 "array concatenation with wrong type",
3848 \\const src = "aoeu";3889 \\const src = "aoeu";
3849 \\const derp = @as(usize, 1234);3890 \\const derp: usize = 1234;
3850 \\const a = derp ++ "foo";3891 \\const a = derp ++ "foo";
3851 \\3892 \\
3852 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }3893 \\export fn entry() usize { return @sizeOf(@typeOf(a)); }
3853 ,3894 ,
3854 "tmp.zig:3:11: error: expected array or C string literal, found 'usize'",3895 "tmp.zig:3:11: error: expected array, found 'usize'",
3855 );3896 );
38563897
3857 cases.add(3898 cases.add(
...@@ -4805,7 +4846,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4805,7 +4846,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4805 cases.add(4846 cases.add(
4806 "assign through constant pointer",4847 "assign through constant pointer",
4807 \\export fn f() void {4848 \\export fn f() void {
4808 \\ var cstr = c"Hat";4849 \\ var cstr = "Hat";
4809 \\ cstr[0] = 'W';4850 \\ cstr[0] = 'W';
4810 \\}4851 \\}
4811 ,4852 ,
...@@ -6226,11 +6267,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6226,11 +6267,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6226 cases.add(6267 cases.add(
6227 "calling var args extern function, passing array instead of pointer",6268 "calling var args extern function, passing array instead of pointer",
6228 \\export fn entry() void {6269 \\export fn entry() void {
6229 \\ foo("hello",);6270 \\ foo("hello".*,);
6230 \\}6271 \\}
6231 \\pub extern fn foo(format: *const u8, ...) void;6272 \\pub extern fn foo(format: *const u8, ...) void;
6232 ,6273 ,
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'",
6234 );6275 );
62356276
6236 cases.add(6277 cases.add(
...@@ -6796,7 +6837,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6796,7 +6837,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6796 \\}6837 \\}
6797 ,6838 ,
6798 "tmp.zig:4:22: error: expected type '*[1]i32', found '*const i32'",6839 "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",
6800 );6841 );
68016842
6802 cases.add(6843 cases.add(
test/stage1/behavior/array.zig+33-6
...@@ -132,9 +132,16 @@ test "single-item pointer to array indexing and slicing" {...@@ -132,9 +132,16 @@ test "single-item pointer to array indexing and slicing" {
132}132}
133133
134fn testSingleItemPtrArrayIndexSlice() void {134fn testSingleItemPtrArrayIndexSlice() void {
135 var array = "aaaa";135 {
136 doSomeMangling(&array);136 var array: [4]u8 = "aaaa".*;
137 expect(mem.eql(u8, "azya", array));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 }
138}145}
139146
140fn doSomeMangling(array: *[4]u8) void {147fn doSomeMangling(array: *[4]u8) void {
...@@ -294,9 +301,16 @@ test "read/write through global variable array of struct fields initialized via...@@ -294,9 +301,16 @@ test "read/write through global variable array of struct fields initialized via
294}301}
295302
296test "implicit cast zero sized array ptr to slice" {303test "implicit cast zero sized array ptr to slice" {
297 var b = "";304 {
298 const c: []const u8 = &b;305 var b = "".*;
299 expect(c.len == 0);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 }
300}314}
301315
302test "anonymous list literal syntax" {316test "anonymous list literal syntax" {
...@@ -333,3 +347,16 @@ test "anonymous literal in array" {...@@ -333,3 +347,16 @@ test "anonymous literal in array" {
333 S.doTheTest();347 S.doTheTest();
334 comptime S.doTheTest();348 comptime S.doTheTest();
335}349}
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" {...@@ -8,8 +8,16 @@ test "comptime code should not modify constant data" {
8}8}
99
10fn testCastPtrOfArrayToSliceAndPtr() void {10fn testCastPtrOfArrayToSliceAndPtr() void {
11 var array = "aoeu";11 {
12 const x: [*]u8 = &array;12 var array = "aoeu".*;
13 x[0] += 1;13 const x: [*]u8 = &array;
14 expect(mem.eql(u8, array[0..], "boeu"));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 }
15}23}
test/stage1/behavior/cast.zig+137-28
...@@ -179,18 +179,24 @@ fn gimmeErrOrSlice() anyerror![]u8 {...@@ -179,18 +179,24 @@ fn gimmeErrOrSlice() anyerror![]u8 {
179}179}
180180
181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {181test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
182 {182 const S = struct {
183 var data = "hi";183 fn doTheTest() anyerror!void {
184 const slice = data[0..];184 {
185 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);185 var data = "hi".*;
186 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);186 const slice = data[0..];
187 }187 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
188 comptime {188 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
189 var data = "hi";189 }
190 const slice = data[0..];190 {
191 expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);191 var data: [2]u8 = "hi".*;
192 expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);192 const slice = data[0..];
193 }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();
194}200}
195fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {201fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
196 if (a) {202 if (a) {
...@@ -217,11 +223,20 @@ test "implicit cast from &const [N]T to []const T" {...@@ -217,11 +223,20 @@ test "implicit cast from &const [N]T to []const T" {
217}223}
218224
219fn testCastConstArrayRefToConstSlice() void {225fn testCastConstArrayRefToConstSlice() void {
220 const blah = "aoeu";226 {
221 const const_array_ref = &blah;227 const blah = "aoeu".*;
222 expect(@typeOf(const_array_ref) == *const [4]u8);228 const const_array_ref = &blah;
223 const slice: []const u8 = const_array_ref;229 expect(@typeOf(const_array_ref) == *const [4:0]u8);
224 expect(mem.eql(u8, slice, "aoeu"));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 }
225}240}
226241
227test "peer type resolution: error and [N]T" {242test "peer type resolution: error and [N]T" {
...@@ -310,19 +325,30 @@ test "single-item pointer of array to slice and to unknown length pointer" {...@@ -310,19 +325,30 @@ test "single-item pointer of array to slice and to unknown length pointer" {
310}325}
311326
312fn testCastPtrOfArrayToSliceAndPtr() void {327fn testCastPtrOfArrayToSliceAndPtr() void {
313 var array = "aoeu";328 {
314 const x: [*]u8 = &array;329 var array = "aoeu".*;
315 x[0] += 1;330 const x: [*]u8 = &array;
316 expect(mem.eql(u8, array[0..], "boeu"));331 x[0] += 1;
317 const y: []u8 = &array;332 expect(mem.eql(u8, array[0..], "boeu"));
318 y[0] += 1;333 const y: []u8 = &array;
319 expect(mem.eql(u8, array[0..], "coeu"));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 }
320}346}
321347
322test "cast *[1][*]const u8 to [*]const ?[*]const u8" {348test "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"};
324 const x: [*]const ?[*]const u8 = &window_name;350 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"));
326}352}
327353
328test "@intCast comptime_int" {354test "@intCast comptime_int" {
...@@ -545,7 +571,7 @@ test "implicit cast *[0]T to E![]const u8" {...@@ -545,7 +571,7 @@ test "implicit cast *[0]T to E![]const u8" {
545}571}
546572
547test "peer cast *[0]T to E![]const T" {573test "peer cast *[0]T to E![]const T" {
548 var buffer: [5]u8 = "abcde";574 var buffer: [5]u8 = "abcde".*;
549 var buf: anyerror![]const u8 = buffer[0..];575 var buf: anyerror![]const u8 = buffer[0..];
550 var b = false;576 var b = false;
551 var y = if (b) &[0]u8{} else buf;577 var y = if (b) &[0]u8{} else buf;
...@@ -553,7 +579,7 @@ test "peer cast *[0]T to E![]const T" {...@@ -553,7 +579,7 @@ test "peer cast *[0]T to E![]const T" {
553}579}
554580
555test "peer cast *[0]T to []const T" {581test "peer cast *[0]T to []const T" {
556 var buffer: [5]u8 = "abcde";582 var buffer: [5]u8 = "abcde".*;
557 var buf: []const u8 = buffer[0..];583 var buf: []const u8 = buffer[0..];
558 var b = false;584 var b = false;
559 var y = if (b) &[0]u8{} else buf;585 var y = if (b) &[0]u8{} else buf;
...@@ -565,3 +591,86 @@ test "cast from array reference to fn" {...@@ -565,3 +591,86 @@ test "cast from array reference to fn" {
565 const f = @ptrCast(extern fn () void, &global_array);591 const f = @ptrCast(extern fn () void, &global_array);
566 expect(@ptrToInt(f) == @ptrToInt(&global_array));592 expect(@ptrToInt(f) == @ptrToInt(&global_array));
567}593}
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;...@@ -6,12 +6,11 @@ var argv: [*]const [*]const u8 = undefined;
66
7test "const slice child" {7test "const slice child" {
8 const strs = [_][*]const u8{8 const strs = [_][*]const u8{
9 c"one",9 "one",
10 c"two",10 "two",
11 c"three",11 "three",
12 };12 };
13 // TODO this should implicitly cast13 argv = &strs;
14 argv = @ptrCast([*]const [*]const u8, &strs);
15 bar(strs.len);14 bar(strs.len);
16}15}
1716
test/stage1/behavior/eval.zig+1-1
...@@ -736,7 +736,7 @@ test "comptime pointer cast array and then slice" {...@@ -736,7 +736,7 @@ test "comptime pointer cast array and then slice" {
736736
737test "slice bounds in comptime concatenation" {737test "slice bounds in comptime concatenation" {
738 const bs = comptime blk: {738 const bs = comptime blk: {
739 const b = c"........1........";739 const b = "........1........";
740 break :blk b[8..9];740 break :blk b[8..9];
741 };741 };
742 const str = "" ++ bs;742 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" {...@@ -81,6 +81,10 @@ test "if prongs cast to expected type instead of peer type resolution" {
81 var x: i32 = 0;81 var x: i32 = 0;
82 x = if (f) 1 else 2;82 x = if (f) 1 else 2;
83 expect(x == 2);83 expect(x == 2);
84
85 var b = true;
86 const y: i32 = if (b) 1 else 2;
87 expect(y == 1);
84 }88 }
85 };89 };
86 S.doTheTest(false);90 S.doTheTest(false);
test/stage1/behavior/misc.zig+10-7
...@@ -204,11 +204,11 @@ test "multiline string" {...@@ -204,11 +204,11 @@ test "multiline string" {
204204
205test "multiline C string" {205test "multiline C string" {
206 const s1 =206 const s1 =
207 c\\one207 \\one
208 c\\two)208 \\two)
209 c\\three209 \\three
210 ;210 ;
211 const s2 = c"one\ntwo)\nthree";211 const s2 = "one\ntwo)\nthree";
212 expect(std.cstr.cmp(s1, s2) == 0);212 expect(std.cstr.cmp(s1, s2) == 0);
213}213}
214214
...@@ -358,9 +358,12 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {...@@ -358,9 +358,12 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
358 return a == b;358 return a == b;
359}359}
360360
361test "C string concatenation" {361test "string concatenation" {
362 const a = c"OK" ++ c" IT " ++ c"WORKED";362 const a = "OK" ++ " IT " ++ "WORKED";
363 const b = c"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
365 const len = mem.len(u8, b);368 const len = mem.len(u8, b);
366 const len_with_null = len + 1;369 const len_with_null = len + 1;
test/stage1/behavior/pointers.zig+63-1
...@@ -15,7 +15,7 @@ fn testDerefPtr() void {...@@ -15,7 +15,7 @@ fn testDerefPtr() void {
15}15}
1616
17test "pointer arithmetic" {17test "pointer arithmetic" {
18 var ptr = c"abcd";18 var ptr: [*]const u8 = "abcd";
1919
20 expect(ptr[0] == 'a');20 expect(ptr[0] == 'a');
21 ptr += 1;21 ptr += 1;
...@@ -200,3 +200,65 @@ test "assign null directly to C pointer and test null equality" {...@@ -200,3 +200,65 @@ test "assign null directly to C pointer and test null equality" {
200 }200 }
201 comptime expect((y1 orelse &othery) == y1);201 comptime expect((y1 orelse &othery) == y1);
202}202}
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" {...@@ -60,7 +60,7 @@ test "comptime ptrcast keeps larger alignment" {
60}60}
6161
62test "implicit optional pointer to optional c_void pointer" {62test "implicit optional pointer to optional c_void pointer" {
63 var buf: [4]u8 = "aoeu";63 var buf: [4]u8 = "aoeu".*;
64 var x: ?[*]u8 = &buf;64 var x: ?[*]u8 = &buf;
65 var y: ?*c_void = x;65 var y: ?*c_void = x;
66 var z = @ptrCast(*[4]u8, y);66 var z = @ptrCast(*[4]u8, y);
test/stage1/behavior/slice.zig+14-1
...@@ -36,7 +36,7 @@ fn assertLenIsZero(msg: []const u8) void {...@@ -36,7 +36,7 @@ fn assertLenIsZero(msg: []const u8) void {
36}36}
3737
38test "C pointer" {38test "C pointer" {
39 var buf: [*c]const u8 = c"kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";39 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
40 var len: u32 = 10;40 var len: u32 = 10;
41 var slice = buf[0..len];41 var slice = buf[0..len];
42 expectEqualSlices(u8, "kjdhfkjdhf", slice);42 expectEqualSlices(u8, "kjdhfkjdhf", slice);
...@@ -65,3 +65,16 @@ test "slice type with custom alignment" {...@@ -65,3 +65,16 @@ test "slice type with custom alignment" {
65 slice[1].anything = 42;65 slice[1].anything = 42;
66 expect(array[1].anything == 42);66 expect(array[1].anything == 42);
67}67}
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" {...@@ -493,7 +493,7 @@ test "non-byte-aligned array inside packed struct" {
493 fn doTheTest() void {493 fn doTheTest() void {
494 var foo = Foo{494 var foo = Foo{
495 .a = true,495 .a = true,
496 .b = "abcdefghijklmnopqurstu",496 .b = "abcdefghijklmnopqurstu".*,
497 };497 };
498 bar(foo.b);498 bar(foo.b);
499 }499 }
...@@ -777,3 +777,16 @@ test "anonymous struct literal assigned to variable" {...@@ -777,3 +777,16 @@ test "anonymous struct literal assigned to variable" {
777 vec.@"1" += 1;777 vec.@"1" += 1;
778 expect(vec.@"1" == 56);778 expect(vec.@"1" == 56);
779}779}
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 {...@@ -11,103 +11,122 @@ fn testTypes(comptime types: []const type) void {
11}11}
1212
13test "Type.MetaType" {13test "Type.MetaType" {
14 testing.expect(type == @Type(TypeInfo { .Type = undefined }));14 testing.expect(type == @Type(TypeInfo{ .Type = undefined }));
15 testTypes([_]type {type});15 testTypes([_]type{type});
16}16}
1717
18test "Type.Void" {18test "Type.Void" {
19 testing.expect(void == @Type(TypeInfo { .Void = undefined }));19 testing.expect(void == @Type(TypeInfo{ .Void = undefined }));
20 testTypes([_]type {void});20 testTypes([_]type{void});
21}21}
2222
23test "Type.Bool" {23test "Type.Bool" {
24 testing.expect(bool == @Type(TypeInfo { .Bool = undefined }));24 testing.expect(bool == @Type(TypeInfo{ .Bool = undefined }));
25 testTypes([_]type {bool});25 testTypes([_]type{bool});
26}26}
2727
28test "Type.NoReturn" {28test "Type.NoReturn" {
29 testing.expect(noreturn == @Type(TypeInfo { .NoReturn = undefined }));29 testing.expect(noreturn == @Type(TypeInfo{ .NoReturn = undefined }));
30 testTypes([_]type {noreturn});30 testTypes([_]type{noreturn});
31}31}
3232
33test "Type.Int" {33test "Type.Int" {
34 testing.expect(u1 == @Type(TypeInfo { .Int = TypeInfo.Int { .is_signed = false, .bits = 1 } }));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 } }));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 } }));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 } }));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 } }));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 } }));39 testing.expect(i64 == @Type(TypeInfo{ .Int = TypeInfo.Int{ .is_signed = true, .bits = 64 } }));
40 testTypes([_]type {u8,u32,i64});40 testTypes([_]type{ u8, u32, i64 });
41}41}
4242
43test "Type.Float" {43test "Type.Float" {
44 testing.expect(f16 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 16 } }));44 testing.expect(f16 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 16 } }));
45 testing.expect(f32 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 32 } }));45 testing.expect(f32 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 32 } }));
46 testing.expect(f64 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 64 } }));46 testing.expect(f64 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 64 } }));
47 testing.expect(f128 == @Type(TypeInfo { .Float = TypeInfo.Float { .bits = 128 } }));47 testing.expect(f128 == @Type(TypeInfo{ .Float = TypeInfo.Float{ .bits = 128 } }));
48 testTypes([_]type {f16, f32, f64, f128});48 testTypes([_]type{ f16, f32, f64, f128 });
49}49}
5050
51test "Type.Pointer" {51test "Type.Pointer" {
52 testTypes([_]type {52 testTypes([_]type{
53 // One Value Pointer Types53 // One Value Pointer Types
54 *u8, *const u8,54 *u8, *const u8,
55 *volatile u8, *const volatile u8,55 *volatile u8, *const volatile u8,
56 *align(4) u8, *const align(4) u8,56 *align(4) u8, *align(4) const u8,
57 *volatile align(4) u8, *const volatile align(4) u8,57 *align(4) volatile u8, *align(4) const volatile u8,
58 *align(8) u8, *const align(8) u8,58 *align(8) u8, *align(8) const u8,
59 *volatile align(8) u8, *const volatile align(8) u8,59 *align(8) volatile u8, *align(8) const volatile u8,
60 *allowzero u8, *const allowzero u8,60 *allowzero u8, *allowzero const u8,
61 *volatile allowzero u8, *const volatile allowzero u8,61 *allowzero volatile u8, *allowzero const volatile u8,
62 *align(4) allowzero u8, *const align(4) allowzero u8,62 *allowzero align(4) u8, *allowzero align(4) const u8,
63 *volatile align(4) allowzero u8, *const volatile align(4) allowzero u8,63 *allowzero align(4) volatile u8, *allowzero align(4) const volatile u8,
64 // Many Values Pointer Types64 // Many Values Pointer Types
65 [*]u8, [*]const u8,65 [*]u8, [*]const u8,
66 [*]volatile u8, [*]const volatile u8,66 [*]volatile u8, [*]const volatile u8,
67 [*]align(4) u8, [*]const align(4) u8,67 [*]align(4) u8, [*]align(4) const u8,
68 [*]volatile align(4) u8, [*]const volatile align(4) u8,68 [*]align(4) volatile u8, [*]align(4) const volatile u8,
69 [*]align(8) u8, [*]const align(8) u8,69 [*]align(8) u8, [*]align(8) const u8,
70 [*]volatile align(8) u8, [*]const volatile align(8) u8,70 [*]align(8) volatile u8, [*]align(8) const volatile u8,
71 [*]allowzero u8, [*]const allowzero u8,71 [*]allowzero u8, [*]allowzero const u8,
72 [*]volatile allowzero u8, [*]const volatile allowzero u8,72 [*]allowzero volatile u8, [*]allowzero const volatile u8,
73 [*]align(4) allowzero u8, [*]const align(4) allowzero u8,73 [*]allowzero align(4) u8, [*]allowzero align(4) const u8,
74 [*]volatile align(4) allowzero u8, [*]const volatile align(4) allowzero u8,74 [*]allowzero align(4) volatile u8, [*]allowzero align(4) const volatile u8,
75 // Slice Types75 // Slice Types
76 []u8, []const u8,76 []u8, []const u8,
77 []volatile u8, []const volatile u8,77 []volatile u8, []const volatile u8,
78 []align(4) u8, []const align(4) u8,78 []align(4) u8, []align(4) const u8,
79 []volatile align(4) u8, []const volatile align(4) u8,79 []align(4) volatile u8, []align(4) const volatile u8,
80 []align(8) u8, []const align(8) u8,80 []align(8) u8, []align(8) const u8,
81 []volatile align(8) u8, []const volatile align(8) u8,81 []align(8) volatile u8, []align(8) const volatile u8,
82 []allowzero u8, []const allowzero u8,82 []allowzero u8, []allowzero const u8,
83 []volatile allowzero u8, []const volatile allowzero u8,83 []allowzero volatile u8, []allowzero const volatile u8,
84 []align(4) allowzero u8, []const align(4) allowzero u8,84 []allowzero align(4) u8, []allowzero align(4) const u8,
85 []volatile align(4) allowzero u8, []const volatile align(4) allowzero u8,85 []allowzero align(4) volatile u8, []allowzero align(4) const volatile u8,
86 // C Pointer Types86 // C Pointer Types
87 [*c]u8, [*c]const u8,87 [*c]u8, [*c]const u8,
88 [*c]volatile u8, [*c]const volatile u8,88 [*c]volatile u8, [*c]const volatile u8,
89 [*c]align(4) u8, [*c]const align(4) u8,89 [*c]align(4) u8, [*c]align(4) const u8,
90 [*c]volatile align(4) u8, [*c]const volatile align(4) u8,90 [*c]align(4) volatile u8, [*c]align(4) const volatile u8,
91 [*c]align(8) u8, [*c]const align(8) u8,91 [*c]align(8) u8, [*c]align(8) const u8,
92 [*c]volatile align(8) u8, [*c]const volatile align(8) u8,92 [*c]align(8) volatile u8, [*c]align(8) const volatile u8,
93 });93 });
94}94}
9595
96test "Type.Array" {96test "Type.Array" {
97 testing.expect([123]u8 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 123, .child = u8 } }));97 testing.expect([123]u8 == @Type(TypeInfo{
98 testing.expect([2]u32 == @Type(TypeInfo { .Array = TypeInfo.Array { .len = 2, .child = u32 } }));98 .Array = TypeInfo.Array{
99 testTypes([_]type {[1]u8, [30]usize, [7]bool});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 });
100}119}
101120
102test "Type.ComptimeFloat" {121test "Type.ComptimeFloat" {
103 testTypes([_]type {comptime_float});122 testTypes([_]type{comptime_float});
104}123}
105test "Type.ComptimeInt" {124test "Type.ComptimeInt" {
106 testTypes([_]type {comptime_int});125 testTypes([_]type{comptime_int});
107}126}
108test "Type.Undefined" {127test "Type.Undefined" {
109 testTypes([_]type {@typeOf(undefined)});128 testTypes([_]type{@typeOf(undefined)});
110}129}
111test "Type.Null" {130test "Type.Null" {
112 testTypes([_]type {@typeOf(null)});131 testTypes([_]type{@typeOf(null)});
113}132}
test/stage1/behavior/type_info.zig+26-5
...@@ -46,6 +46,7 @@ fn testPointer() void {...@@ -46,6 +46,7 @@ fn testPointer() void {
46 expect(u32_ptr_info.Pointer.is_volatile == false);46 expect(u32_ptr_info.Pointer.is_volatile == false);
47 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));47 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
48 expect(u32_ptr_info.Pointer.child == u32);48 expect(u32_ptr_info.Pointer.child == u32);
49 expect(u32_ptr_info.Pointer.sentinel == null);
49}50}
5051
51test "type info: unknown length pointer type info" {52test "type info: unknown length pointer type info" {
...@@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" {...@@ -55,14 +56,34 @@ test "type info: unknown length pointer type info" {
5556
56fn testUnknownLenPtr() void {57fn testUnknownLenPtr() void {
57 const u32_ptr_info = @typeInfo([*]const volatile f64);58 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);
59 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);60 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
60 expect(u32_ptr_info.Pointer.is_const == true);61 expect(u32_ptr_info.Pointer.is_const == true);
61 expect(u32_ptr_info.Pointer.is_volatile == true);62 expect(u32_ptr_info.Pointer.is_volatile == true);
63 expect(u32_ptr_info.Pointer.sentinel == null);
62 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));64 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
63 expect(u32_ptr_info.Pointer.child == f64);65 expect(u32_ptr_info.Pointer.child == f64);
64}66}
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
66test "type info: C pointer type info" {87test "type info: C pointer type info" {
67 testCPtr();88 testCPtr();
68 comptime testCPtr();89 comptime testCPtr();
...@@ -70,7 +91,7 @@ test "type info: C pointer type info" {...@@ -70,7 +91,7 @@ test "type info: C pointer type info" {
7091
71fn testCPtr() void {92fn testCPtr() void {
72 const ptr_info = @typeInfo([*c]align(4) const i8);93 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);
74 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);95 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.C);
75 expect(ptr_info.Pointer.is_const);96 expect(ptr_info.Pointer.is_const);
76 expect(!ptr_info.Pointer.is_volatile);97 expect(!ptr_info.Pointer.is_volatile);
...@@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" {...@@ -288,13 +309,13 @@ test "type info: anyframe and anyframe->T" {
288fn testAnyFrame() void {309fn testAnyFrame() void {
289 {310 {
290 const anyframe_info = @typeInfo(anyframe->i32);311 const anyframe_info = @typeInfo(anyframe->i32);
291 expect(@as(TypeId,anyframe_info) == .AnyFrame);312 expect(@as(TypeId, anyframe_info) == .AnyFrame);
292 expect(anyframe_info.AnyFrame.child.? == i32);313 expect(anyframe_info.AnyFrame.child.? == i32);
293 }314 }
294315
295 {316 {
296 const anyframe_info = @typeInfo(anyframe);317 const anyframe_info = @typeInfo(anyframe);
297 expect(@as(TypeId,anyframe_info) == .AnyFrame);318 expect(@as(TypeId, anyframe_info) == .AnyFrame);
298 expect(anyframe_info.AnyFrame.child == null);319 expect(anyframe_info.AnyFrame.child == null);
299 }320 }
300}321}
...@@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" {...@@ -334,7 +355,7 @@ test "type info: extern fns with and without lib names" {
334 if (std.mem.eql(u8, decl.name, "bar1")) {355 if (std.mem.eql(u8, decl.name, "bar1")) {
335 expect(decl.data.Fn.lib_name == null);356 expect(decl.data.Fn.lib_name == null);
336 } else {357 } 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.?);
338 }359 }
339 }360 }
340 }361 }
test/stage1/c_abi/main.zig+1-1
...@@ -119,7 +119,7 @@ export fn zig_bool(x: bool) void {...@@ -119,7 +119,7 @@ export fn zig_bool(x: bool) void {
119extern fn c_array([10]u8) void;119extern fn c_array([10]u8) void;
120120
121test "C ABI array" {121test "C ABI array" {
122 var array: [10]u8 = "1234567890";122 var array: [10]u8 = "1234567890".*;
123 c_array(array);123 c_array(array);
124}124}
125125
test/stage2/compare_output.zig+2-2
...@@ -6,7 +6,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -6,7 +6,7 @@ pub fn addCases(ctx: *TestContext) !void {
6 try ctx.testCompareOutputLibC(6 try ctx.testCompareOutputLibC(
7 \\extern fn puts([*]const u8) void;7 \\extern fn puts([*]const u8) void;
8 \\export fn main() c_int {8 \\export fn main() c_int {
9 \\ puts(c"Hello, world!");9 \\ puts("Hello, world!");
10 \\ return 0;10 \\ return 0;
11 \\}11 \\}
12 , "Hello, world!" ++ std.cstr.line_sep);12 , "Hello, world!" ++ std.cstr.line_sep);
...@@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
15 try ctx.testCompareOutputLibC(15 try ctx.testCompareOutputLibC(
16 \\extern fn puts(s: [*]const u8) void;16 \\extern fn puts(s: [*]const u8) void;
17 \\export fn main() c_int {17 \\export fn main() c_int {
18 \\ return foo(c"OK");18 \\ return foo("OK");
19 \\}19 \\}
20 \\fn foo(s: [*]const u8) c_int {20 \\fn foo(s: [*]const u8) c_int {
21 \\ puts(s);21 \\ puts(s);
test/standalone/hello_world/hello_libc.zig+1-1
...@@ -5,7 +5,7 @@ const c = @cImport({...@@ -5,7 +5,7 @@ const c = @cImport({
5 @cInclude("string.h");5 @cInclude("string.h");
6});6});
77
8const msg = c"Hello, world!\n";8const msg = "Hello, world!\n";
99
10export fn main(argc: c_int, argv: **u8) c_int {10export fn main(argc: c_int, argv: **u8) c_int {
11 if (c.printf(msg) != @intCast(c_int, c.strlen(msg))) return -1;11 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 {...@@ -47,7 +47,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
47 \\pub fn foo() void {47 \\pub fn foo() void {
48 \\ var a: c_int = undefined;48 \\ var a: c_int = undefined;
49 \\ _ = 1;49 \\ _ = 1;
50 \\ _ = c"hey";50 \\ _ = "hey";
51 \\ _ = (1 + 1);51 \\ _ = (1 + 1);
52 \\ _ = (1 - 1);52 \\ _ = (1 - 1);
53 \\ a = 1;53 \\ a = 1;
...@@ -213,9 +213,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -213,9 +213,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
213 \\}213 \\}
214 ,214 ,
215 \\pub fn foo() void {215 \\pub fn foo() void {
216 \\ _ = c"foo";216 \\ _ = "foo";
217 \\ _ = c"foo";217 \\ _ = "foo";
218 \\ _ = c"void foo(void)";218 \\ _ = "void foo(void)";
219 \\}219 \\}
220 );220 );
221221
...@@ -232,7 +232,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -232,7 +232,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
232 \\pub fn foo() void {232 \\pub fn foo() void {
233 \\ var a: c_int = undefined;233 \\ var a: c_int = undefined;
234 \\ _ = 1;234 \\ _ = 1;
235 \\ _ = c"hey";235 \\ _ = "hey";
236 \\ _ = (1 + 1);236 \\ _ = (1 + 1);
237 \\ _ = (1 - 1);237 \\ _ = (1 - 1);
238 \\ a = 1;238 \\ a = 1;
...@@ -543,7 +543,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -543,7 +543,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
543 cases.add("#define string",543 cases.add("#define string",
544 \\#define foo "a string"544 \\#define foo "a string"
545 ,545 ,
546 \\pub const foo = c"a string";546 \\pub const foo = "a string";
547 );547 );
548548
549 cases.add("__cdecl doesn't mess up function pointers",549 cases.add("__cdecl doesn't mess up function pointers",
...@@ -617,9 +617,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -617,9 +617,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
617 \\#define FOO2 "aoeu\x0007a derp"617 \\#define FOO2 "aoeu\x0007a derp"
618 \\#define FOO_CHAR '\xfF'618 \\#define FOO_CHAR '\xfF'
619 ,619 ,
620 \\pub const FOO = c"aoeu\xab derp";620 \\pub const FOO = "aoeu\xab derp";
621 ,621 ,
622 \\pub const FOO2 = c"aoeuz derp";622 \\pub const FOO2 = "aoeuz derp";
623 ,623 ,
624 \\pub const FOO_CHAR = 255;624 \\pub const FOO_CHAR = 255;
625 );625 );
...@@ -629,9 +629,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -629,9 +629,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
629 \\#define FOO2 "aoeu\0234 derp"629 \\#define FOO2 "aoeu\0234 derp"
630 \\#define FOO_CHAR '\077'630 \\#define FOO_CHAR '\077'
631 ,631 ,
632 \\pub const FOO = c"aoeu\x13 derp";632 \\pub const FOO = "aoeu\x13 derp";
633 ,633 ,
634 \\pub const FOO2 = c"aoeu\x134 derp";634 \\pub const FOO2 = "aoeu\x134 derp";
635 ,635 ,
636 \\pub const FOO_CHAR = 63;636 \\pub const FOO_CHAR = 63;
637 );637 );
...@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1351 \\}1351 \\}
1352 ,1352 ,
1353 \\pub fn foo() [*c]const u8 {1353 \\pub fn foo() [*c]const u8 {
1354 \\ return c"bar";1354 \\ return "bar";
1355 \\}1355 \\}
1356 );1356 );
13571357
...@@ -1523,7 +1523,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1523,7 +1523,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1523 cases.add("const ptr initializer",1523 cases.add("const ptr initializer",
1524 \\static const char *v0 = "0.0.0";1524 \\static const char *v0 = "0.0.0";
1525 ,1525 ,
1526 \\pub var v0: [*c]const u8 = c"0.0.0";1526 \\pub var v0: [*c]const u8 = "0.0.0";
1527 );1527 );
15281528
1529 cases.add("static incomplete array inside function",1529 cases.add("static incomplete array inside function",
...@@ -1532,7 +1532,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1532,7 +1532,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1532 \\}1532 \\}
1533 ,1533 ,
1534 \\pub fn foo() void {1534 \\pub fn foo() void {
1535 \\ const v2: [*c]const u8 = c"2.2.2";1535 \\ const v2: [*c]const u8 = "2.2.2";
1536 \\}1536 \\}
1537 );1537 );
15381538
...@@ -1809,7 +1809,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {...@@ -1809,7 +1809,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
1809 \\ var i: u8 = @as(u8, '\x0b');1809 \\ var i: u8 = @as(u8, '\x0b');
1810 \\ var j: u8 = @as(u8, '\x00');1810 \\ var j: u8 = @as(u8, '\x00');
1811 \\ var k: u8 = @as(u8, '\"');1811 \\ 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\"";
1813 \\}1813 \\}
1814 \\1814 \\
1815 );1815 );