| author | |
| committer | |
| log | 5a98dd42b38b9188cfb96c9ab57dc91af923029f |
| tree | 5b48dea38aeb28cf82b9ee98092bad4aea004d90 |
| parent | 69b780647abd14f0809a58006242397f3e94ac51 |
| parent | 321726465d3151d80e651b0c3001177a3ef53fff |
| signature |
sentinel-terminated pointers80 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]), |
| 960 | 958 | ||
| 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 as | 556 | 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; |
| 558 | const mem = @import("std").mem; | 562 | const mem = @import("std").mem; |
| 559 | 563 | ||
| 560 | test "string literals" { | 564 | test "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#} | ||
| 648 | const 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 | } |
| 1640 | 1622 | ||
| 1641 | // a string literal is an array literal | 1623 | // A string literal is a pointer to an array literal. |
| 1642 | const same_message = "hello"; | 1624 | const same_message = "hello".*; |
| 1643 | 1625 | ||
| 1644 | comptime { | 1626 | comptime { |
| 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 | } |
| 1648 | 1629 | ||
| 1649 | test "iterate over an array" { | 1630 | test "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#} | ||
| 1790 | const std = @import("std"); | ||
| 1791 | const assert = std.debug.assert; | ||
| 1792 | |||
| 1793 | test "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#} |
| 1803 | 1804 | ||
| 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#} | ||
| 2123 | const std = @import("std"); | ||
| 2124 | |||
| 2125 | // This is also available as `std.c.printf`. | ||
| 2126 | pub extern "c" fn printf(format: [*:0]const u8, ...) c_int; | ||
| 2127 | |||
| 2128 | pub 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#} |
| 2115 | 2139 | ||
| 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#} | ||
| 2230 | const std = @import("std"); | ||
| 2231 | const assert = std.debug.assert; | ||
| 2232 | |||
| 2233 | test "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; |
| 4817 | const mem = std.mem; | 4863 | const mem = std.mem; |
| 4818 | 4864 | ||
| 4819 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | 4865 | test "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#} |
| 4863 | const std = @import("std"); | 4909 | const std = @import("std"); |
| 4864 | const assert = std.debug.assert; | 4910 | const assert = std.debug.assert; |
| 4865 | 4911 | ||
| ... | @@ -4898,7 +4944,7 @@ test "[N]T to ?[]const T" { | ... | @@ -4898,7 +4944,7 @@ test "[N]T to ?[]const T" { |
| 4898 | 4944 | ||
| 4899 | // In this cast, the array length becomes the slice length. | 4945 | // In this cast, the array length becomes the slice length. |
| 4900 | test "*[N]T to []T" { | 4946 | test "*[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")); |
| 4904 | 4950 | ||
| ... | @@ -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 to | 4956 | // Single-item pointers to arrays can be coerced to |
| 4911 | // unknown length pointers. | 4957 | // unknown length pointers. |
| 4912 | test "*[N]T to [*]T" { | 4958 | test "*[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" { |
| 4918 | 4964 | ||
| 4919 | // Likewise, it works when the destination type is an optional. | 4965 | // Likewise, it works when the destination type is an optional. |
| 4920 | test "*[N]T to ?[*]T" { | 4966 | test "*[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 are | 5135 | 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#} |
| 5093 | const std = @import("std"); | 5139 | const std = @import("std"); |
| 5094 | const assert = std.debug.assert; | 5140 | const assert = std.debug.assert; |
| 5095 | const mem = std.mem; | 5141 | const 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 | } |
| 5157 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | 5203 | test "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#} |
| 8629 | comptime { | 8675 | comptime { |
| 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#} | ||
| 9609 | extern fn puts([*]const u8) void; | ||
| 9610 | |||
| 9611 | pub 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#} | ||
| 9622 | 9652 | ||
| 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 | }); |
| 9635 | pub fn main() void { | 9665 | pub 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 | } |
| 74 | 74 | ||
| 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 | } |
| 78 | 78 | ||
| 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 | } |
| 82 | 82 | ||
| ... | @@ -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 | }; |
| 140 | 135 | ||
| 141 | test "simple Buffer" { | 136 | test "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, | ||
| 147 | 151 | ||
| 148 | /// This data structure is used by the Zig language code generation and | 152 | /// 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 | }; |
| 164 | 172 | ||
| 165 | /// This data structure is used by the Zig language code generation and | 173 | /// 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; |
| 63 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; | 63 | pub extern "c" fn fwrite(ptr: [*]const u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; |
| 64 | pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; | 64 | pub extern "c" fn fread(ptr: [*]u8, size_of_type: usize, item_count: usize, stream: *FILE) usize; |
| 65 | 65 | ||
| 66 | pub extern "c" fn printf(format: [*]const u8, ...) c_int; | 66 | pub extern "c" fn printf(format: [*:0]const u8, ...) c_int; |
| 67 | pub extern "c" fn abort() noreturn; | 67 | pub extern "c" fn abort() noreturn; |
| 68 | pub extern "c" fn exit(code: c_int) noreturn; | 68 | pub extern "c" fn exit(code: c_int) noreturn; |
| 69 | pub extern "c" fn isatty(fd: fd_t) c_int; | 69 | pub 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: [ |
| 102 | pub extern "c" fn dup(fd: fd_t) c_int; | 102 | pub extern "c" fn dup(fd: fd_t) c_int; |
| 103 | pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int; | 103 | pub extern "c" fn dup2(old_fd: fd_t, new_fd: fd_t) c_int; |
| 104 | pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize; | 104 | pub extern "c" fn readlink(noalias path: [*]const u8, noalias buf: [*]u8, bufsize: usize) isize; |
| 105 | pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*]u8; | 105 | pub extern "c" fn realpath(noalias file_name: [*]const u8, noalias resolved_name: [*]u8) ?[*:0]u8; |
| 106 | pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int; | 106 | pub extern "c" fn sigprocmask(how: c_int, noalias set: *const sigset_t, noalias oset: ?*sigset_t) c_int; |
| 107 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; | 107 | pub extern "c" fn gettimeofday(noalias tv: ?*timeval, noalias tz: ?*timezone) c_int; |
| 108 | pub extern "c" fn sigaction(sig: c_int, noalias act: *const Sigaction, noalias oact: ?*Sigaction) c_int; | 108 | pub 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; |
| 110 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; | 110 | pub extern "c" fn setreuid(ruid: c_uint, euid: c_uint) c_int; |
| 111 | pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int; | 111 | pub extern "c" fn setregid(rgid: c_uint, egid: c_uint) c_int; |
| 112 | pub extern "c" fn rmdir(path: [*]const u8) c_int; | 112 | pub extern "c" fn rmdir(path: [*]const u8) c_int; |
| 113 | pub extern "c" fn getenv(name: [*]const u8) ?[*]u8; | 113 | pub extern "c" fn getenv(name: [*:0]const u8) ?[*:0]u8; |
| 114 | pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | 114 | pub extern "c" fn sysctl(name: [*]const c_int, namelen: c_uint, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; |
| 115 | pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; | 115 | pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; |
| 116 | pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; | 116 | pub 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 { |
| 330 | 330 | ||
| 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 { |
| 441 | 441 | ||
| 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); |
| 443 | 443 | ||
| 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 | } |
| 611 | 611 | ||
| 612 | test "x25519 rfc7748 one iteration" { | 612 | test "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".*; |
| 615 | 615 | ||
| 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 | } |
| 636 | 636 | ||
| 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".*; |
| 639 | 639 | ||
| 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 | } |
| 659 | 659 | ||
| 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".*; |
| 662 | 662 | ||
| 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 | } |
| 28 | 28 | ||
| 29 | fn testCStrFnsImpl() void { | 29 | fn 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 | } |
| 33 | 33 | ||
| 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 | }; |
| 705 | 705 | ||
| 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)); |
| 1712 | 1712 | ||
| 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 and | 1741 | 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 | } |
| 2325 | 2325 | ||
| 2326 | fn readStringMem(ptr: *[*]const u8) []const u8 { | 2326 | fn 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 | }; |
| 141 | 141 | ||
| 142 | pub const ElfLib = struct { | 142 | pub 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; |
| 177 | 177 | ||
| 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 | }; |
| 232 | 232 | ||
| 233 | fn checkver(def_arg: *elf.Verdef, vsym_arg: i32, vername: []const u8, strings: [*]u8) bool { | 233 | fn 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 | }; |
| 59 | 59 | ||
| 60 | pub const Open = struct { | 60 | pub const Open = struct { |
| 61 | /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265 | 61 | 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 | }; |
| 69 | 68 | ||
| 70 | pub const WriteFile = struct { | 69 | pub const WriteFile = struct { |
| 71 | /// must be null terminated. TODO https://github.com/ziglang/zig/issues/265 | 70 | 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 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const math = std.math; | 2 | const math = std.math; |
| 3 | const debug = std.debug; | 3 | const assert = std.debug.assert; |
| 4 | const assert = debug.assert; | ||
| 5 | const testing = std.testing; | ||
| 6 | const mem = std.mem; | 4 | const mem = std.mem; |
| 7 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 8 | const errol = @import("fmt/errol.zig"); | 6 | const 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, |
| 36 | 34 | ||
| 37 | fn peekIsAlign(comptime fmt: []const u8) bool { | 35 | fn 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] == ':'); |
| 40 | 38 | ||
| 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 | } |
| 1010 | 1008 | ||
| 1011 | test "parseInt" { | 1009 | test "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 | } |
| 1020 | 1018 | ||
| 1021 | const ParseUnsignedError = error{ | 1019 | const 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 | } |
| 1041 | 1039 | ||
| 1042 | test "parseUnsigned" { | 1040 | test "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)); |
| 1046 | 1044 | ||
| 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)); |
| 1049 | 1047 | ||
| 1050 | testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); | 1048 | std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF); |
| 1051 | 1049 | ||
| 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); |
| 1054 | 1052 | ||
| 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)); |
| 1057 | 1055 | ||
| 1058 | testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); | 1056 | std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747); |
| 1059 | 1057 | ||
| 1060 | // these numbers should fit even though the radix itself doesn't fit in the destination type | 1058 | // 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 | } |
| 1068 | 1066 | ||
| 1069 | pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; | 1067 | pub 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) { |
| 1134 | test "bufPrintInt" { | 1132 | test "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")); |
| 1141 | 1139 | ||
| 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")); |
| 1143 | 1141 | ||
| 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")); |
| 1147 | 1145 | ||
| 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 | } |
| 1151 | 1149 | ||
| 1152 | fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 { | 1150 | fn 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" { |
| 1163 | 1161 | ||
| 1164 | test "parse unsigned comptime" { | 1162 | test "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 | } |
| 1169 | 1167 | ||
| ... | @@ -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")); |
| 1222 | 1220 | ||
| 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")); |
| 1227 | 1225 | ||
| 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 | } |
| 1234 | 1232 | ||
| 1235 | test "array" { | 1233 | test "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); |
| 1240 | 1238 | ||
| ... | @@ -1278,8 +1276,8 @@ test "pointer" { | ... | @@ -1278,8 +1276,8 @@ test "pointer" { |
| 1278 | } | 1276 | } |
| 1279 | 1277 | ||
| 1280 | test "cstr" { | 1278 | test "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 | } |
| 1284 | 1282 | ||
| 1285 | test "filesize" { | 1283 | test "filesize" { |
| ... | @@ -1479,10 +1477,10 @@ test "union" { | ... | @@ -1479,10 +1477,10 @@ test "union" { |
| 1479 | 1477 | ||
| 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@")); |
| 1483 | 1481 | ||
| 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 | } |
| 1487 | 1485 | ||
| 1488 | test "enum" { | 1486 | test "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 | } |
| 1570 | 1568 | ||
| 1571 | test "trim" { | 1569 | test "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 | } |
| 1578 | 1576 | ||
| 1579 | pub fn isWhiteSpace(byte: u8) bool { | 1577 | pub fn isWhiteSpace(byte: u8) bool { |
| ... | @@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" { | ... | @@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" { |
| 1607 | 1605 | ||
| 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 | } |
| 1612 | 1610 | ||
| 1613 | test "formatType max_depth" { | 1611 | test "formatType max_depth" { |
| ... | @@ -1661,19 +1659,19 @@ test "formatType max_depth" { | ... | @@ -1661,19 +1659,19 @@ test "formatType max_depth" { |
| 1661 | 1659 | ||
| 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{ ... }")); |
| 1665 | 1663 | ||
| 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) }")); |
| 1669 | 1667 | ||
| 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) }")); |
| 1673 | 1671 | ||
| 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 | } |
| 1678 | 1676 | ||
| 1679 | test "positional" { | 1677 | test "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 to | 29 | /// 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. | ||
| 31 | pub const MAX_PATH_BYTES = switch (builtin.os) { | 32 | pub 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); |
| 229 | 230 | ||
| 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 since | 233 | // TODO zig should figure out that this error set does not include PathAlreadyExists since |
| 233 | // it is handled in the above switch | 234 | // 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 | }; |
| 268 | 269 | ||
| ... | @@ -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 | } |
| 275 | 276 | ||
| 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. |
| 277 | pub fn makeDirC(dir_path: [*]const u8) !void { | 278 | pub 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 | } |
| 280 | 281 | ||
| 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. |
| 282 | pub fn makeDirW(dir_path: [*]const u16) !void { | 283 | pub 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 | } |
| 285 | 286 | ||
| ... | @@ -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 | } |
| 328 | 329 | ||
| 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. |
| 330 | pub fn deleteDirC(dir_path: [*]const u8) !void { | 331 | pub fn deleteDirC(dir_path: [*:0]const u8) !void { |
| 331 | return os.rmdirC(dir_path); | 332 | return os.rmdirC(dir_path); |
| 332 | } | 333 | } |
| 333 | 334 | ||
| 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. |
| 335 | pub fn deleteDirW(dir_path: [*]const u16) !void { | 336 | pub fn deleteDirW(dir_path: [*:0]const u16) !void { |
| 336 | return os.rmdirW(dir_path); | 337 | return os.rmdirW(dir_path); |
| 337 | } | 338 | } |
| 338 | 339 | ||
| ... | @@ -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; |
| 535 | 536 | ||
| 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)); |
| 537 | 538 | ||
| 538 | // skip . and .. entries | 539 | // 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 | } |
| 689 | 690 | ||
| 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 | } |
| 694 | 695 | ||
| ... | @@ -708,7 +709,7 @@ pub const Dir = struct { | ... | @@ -708,7 +709,7 @@ pub const Dir = struct { |
| 708 | } | 709 | } |
| 709 | 710 | ||
| 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 | } |
| 721 | 722 | ||
| 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; |
| 724 | 725 | ||
| 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 | } |
| 787 | 788 | ||
| 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 { |
| 805 | 806 | ||
| 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; |
| 810 | 811 | ||
| 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 | } |
| 869 | 870 | ||
| 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_REMOVEDIR | 874 | 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 | } |
| 904 | 905 | ||
| 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_REMOVEDIR | 909 | 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 { |
| 912 | 913 | ||
| 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_REMOVEDIR | 918 | 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 | } |
| 928 | 929 | ||
| 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 | } |
| 933 | 934 | ||
| ... | @@ -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 |
| 1240 | 1241 | ||
| 1241 | pub fn openSelfExe() OpenSelfExeError!File { | 1242 | pub 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 | } |
| 1255 | 1257 | ||
| 1256 | test "openSelfExe" { | 1258 | test "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 | } |
| 1307 | 1309 | ||
| 1308 | /// The result is UTF16LE-encoded. | 1310 | /// The result is UTF16LE-encoded. |
| 1309 | pub fn selfExePathW() []const u16 { | 1311 | pub 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 | } |
| 1313 | 1315 | ||
| 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 directory | 1329 | // 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 dirname | 1332 | // 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 | } |
| 32 | 32 | ||
| 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 | } |
| 37 | 37 | ||
| ... | @@ -61,7 +61,7 @@ pub const File = struct { | ... | @@ -61,7 +61,7 @@ pub const File = struct { |
| 61 | 61 | ||
| 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 { |
| 74 | 74 | ||
| 75 | /// Same as `openWriteMode` except `path` is null-terminated and UTF16LE encoded | 75 | /// 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 | } |
| 102 | 102 | ||
| 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 | } |
| 114 | 114 | ||
| 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 { |
| 142 | 142 | ||
| 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 | } |
| 148 | 148 | ||
| 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 | } |
| 154 | 154 | ||
| ... | @@ -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/3511 | 174 | // 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 | } |
| 395 | 395 | ||
| 396 | // determine which disk designator we will result with, if any | 396 | // 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 |
| 202 | 202 | ||
| 203 | test "siphash64-2-4 sanity" { | 203 | test "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" ... etc | 207 | "\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 | }; |
| 270 | 270 | ||
| 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" { |
| 281 | 281 | ||
| 282 | test "siphash128-2-4 sanity" { | 282 | test "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 | }; |
| 349 | 349 | ||
| 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" { |
| 595 | test "c out stream" { | 595 | test "c out stream" { |
| 596 | if (!builtin.link_libc) return error.SkipZigTest; | 596 | if (!builtin.link_libc) return error.SkipZigTest; |
| 597 | 597 | ||
| 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 | } |
| 358 | 358 | ||
| 359 | pub fn len(comptime T: type, ptr: [*]const T) usize { | 359 | pub 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 | } |
| 364 | 364 | ||
| 365 | pub fn toSliceConst(comptime T: type, ptr: [*]const T) []const T { | 365 | pub 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 | } |
| 368 | 368 | ||
| 369 | pub fn toSlice(comptime T: type, ptr: [*]T) []T { | 369 | pub 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 | } |
| 372 | 372 | ||
| ... | @@ -1408,7 +1408,9 @@ test "toBytes" { | ... | @@ -1408,7 +1408,9 @@ test "toBytes" { |
| 1408 | fn BytesAsValueReturnType(comptime T: type, comptime B: type) type { | 1408 | fn BytesAsValueReturnType(comptime T: type, comptime B: type) type { |
| 1409 | const size = @as(usize, @sizeOf(T)); | 1409 | const size = @as(usize, @sizeOf(T)); |
| 1410 | 1410 | ||
| 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 | } |
| 1414 | 1416 | ||
| ... | @@ -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 | }; |
| 1432 | 1434 | ||
| 1433 | testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*); | 1435 | testing.expect(deadbeef == bytesAsValue(u32, deadbeef_bytes).*); |
| 1434 | 1436 | ||
| 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 | } |
| 1462 | 1464 | ||
| 1463 | ///Given a pointer to an array of bytes, returns a value of the specified type backed by a | 1465 | ///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. |
| 1465 | pub fn bytesToValue(comptime T: type, bytes: var) T { | 1467 | pub fn bytesToValue(comptime T: type, bytes: var) T { |
| 1466 | return bytesAsValue(T, &bytes).*; | 1468 | return bytesAsValue(T, bytes).*; |
| 1467 | } | 1469 | } |
| 1468 | test "bytesToValue" { | 1470 | test "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 | } |
| 1492 | 1494 | ||
| 1493 | test "subArrayPtr" { | 1495 | test "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")); |
| 1497 | 1499 | ||
| 1498 | var a2 = "abcdef"; | 1500 | var a2: [6]u8 = "abcdef".*; |
| 1499 | var sub2 = subArrayPtr(&a2, 2, 3); | 1501 | var sub2 = subArrayPtr(&a2, 2, 3); |
| 1500 | 1502 | ||
| 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 | }; |
| 474 | 474 | ||
| 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 | }; |
| 480 | 480 | ||
| 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 | }; |
| 486 | 486 | ||
| 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)); |
| 496 | 496 | ||
| 497 | var a1 = "abcdef"; | 497 | var a1 = "abcdef".*; |
| 498 | var a2 = "abcdef"; | 498 | var a2 = "abcdef".*; |
| 499 | var a3 = "ghijkl"; | 499 | var a3 = "ghijkl".*; |
| 500 | 500 | ||
| 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 | } |
| 321 | 321 | ||
| 322 | /// | ||
| 323 | pub fn isConstPtr(comptime T: type) bool { | 322 | pub 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 | } |
| 337 | 336 | ||
| 338 | /// | ||
| 339 | pub fn isContainer(comptime T: type) bool { | 337 | pub 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 | } |
| 362 | 362 | ||
| 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 { |
| 666 | 666 | ||
| 667 | const defined_policies = [_]Policy{ | 667 | const 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(); |
| 1008 | 1008 | ||
| 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) { |
| 66 | pub usingnamespace @import("os/bits.zig"); | 66 | pub usingnamespace @import("os/bits.zig"); |
| 67 | 67 | ||
| 68 | /// See also `getenv`. Populated by startup code before main(). | 68 | /// See also `getenv`. Populated by startup code before main(). |
| 69 | pub var environ: [][*]u8 = undefined; | 69 | pub var environ: [][*:0]u8 = undefined; |
| 70 | 70 | ||
| 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. |
| 74 | pub var argv: [][*]u8 = undefined; | 74 | pub var argv: [][*:0]u8 = undefined; |
| 75 | 75 | ||
| 76 | /// To obtain errno, call this function with the return value of the | 76 | /// To obtain errno, call this function with the return value of the |
| 77 | /// system function call. For some systems this will obtain the value directly | 77 | /// 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 | } |
| 158 | 158 | ||
| 159 | fn getRandomBytesDevURandom(buf: []u8) !void { | 159 | fn 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); |
| 162 | 162 | ||
| 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 { |
| 655 | 655 | ||
| 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/265 | 658 | pub fn openC(file_path: [*:0]const u8, flags: u32, perm: usize) OpenError!fd_t { |
| 659 | pub 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`. |
| 700 | pub fn openatC(dir_fd: fd_t, file_path: [*]const u8, flags: u32, mode: usize) OpenError!fd_t { | 699 | pub 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. |
| 760 | pub fn execveC(path: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) ExecveError { | 759 | pub 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`. |
| 787 | pub fn execvpeC(file: [*]const u8, child_argv: [*]const ?[*]const u8, envp: [*]const ?[*]const u8) ExecveError { | 786 | pub 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); |
| 790 | 789 | ||
| ... | @@ -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; |
| 836 | 836 | ||
| 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; |
| 840 | 841 | ||
| 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); |
| 843 | 844 | ||
| 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 | } |
| 846 | 850 | ||
| 847 | pub fn createNullDelimitedEnvMap(allocator: *mem.Allocator, env_map: *const std.BufMap) ![]?[*]u8 { | 851 | pub 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; |
| 861 | 865 | ||
| 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 | } |
| 869 | 875 | ||
| 870 | pub fn freeNullDelimitedEnvMap(allocator: *mem.Allocator, envp_buf: []?[*]u8) void { | 876 | pub 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 { |
| 896 | 902 | ||
| 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/265 | 905 | pub fn getenvC(key: [*:0]const u8) ?[]const u8 { |
| 900 | pub 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! |
| 966 | 971 | ||
| 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`. |
| 969 | pub fn symlinkC(target_path: [*]const u8, sym_link_path: [*]const u8) SymLinkError!void { | 974 | pub 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 | } |
| 1000 | 1005 | ||
| 1001 | pub fn symlinkatC(target_path: [*]const u8, newdirfd: fd_t, sym_link_path: [*]const u8) SymLinkError!void { | 1006 | pub 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 | } |
| 1053 | 1058 | ||
| 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. |
| 1055 | pub fn unlinkC(file_path: [*]const u8) UnlinkError!void { | 1060 | pub 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 | } |
| 1093 | 1098 | ||
| 1094 | /// Same as `unlinkat` but `file_path` is a null-terminated string. | 1099 | /// Same as `unlinkat` but `file_path` is a null-terminated string. |
| 1095 | pub fn unlinkatC(dirfd: fd_t, file_path_c: [*]const u8, flags: u32) UnlinkatError!void { | 1100 | pub 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 | } |
| 1122 | 1127 | ||
| 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. |
| 1124 | pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*]const u16, flags: u32) UnlinkatError!void { | 1129 | pub fn unlinkatW(dirfd: fd_t, sub_path_w: [*:0]const u16, flags: u32) UnlinkatError!void { |
| 1125 | const w = windows; | 1130 | const w = windows; |
| 1126 | 1131 | ||
| 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 | } |
| 1217 | 1222 | ||
| 1218 | /// Same as `rename` except the parameters are null-terminated byte arrays. | 1223 | /// Same as `rename` except the parameters are null-terminated byte arrays. |
| 1219 | pub fn renameC(old_path: [*]const u8, new_path: [*]const u8) RenameError!void { | 1224 | pub 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 { |
| 1248 | 1253 | ||
| 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. |
| 1251 | pub fn renameW(old_path: [*]const u16, new_path: [*]const u16) RenameError!void { | 1256 | pub 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 | } |
| 1283 | 1288 | ||
| 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. |
| 1285 | pub fn mkdirC(dir_path: [*]const u8, mode: u32) MakeDirError!void { | 1290 | pub 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 | } |
| 1333 | 1338 | ||
| 1334 | /// Same as `rmdir` except the parameter is null-terminated. | 1339 | /// Same as `rmdir` except the parameter is null-terminated. |
| 1335 | pub fn rmdirC(dir_path: [*]const u8) DeleteDirError!void { | 1340 | pub 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 | } |
| 1380 | 1385 | ||
| 1381 | /// Same as `chdir` except the parameter is null-terminated. | 1386 | /// Same as `chdir` except the parameter is null-terminated. |
| 1382 | pub fn chdirC(dir_path: [*]const u8) ChangeCurDirError!void { | 1387 | pub 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 | } |
| 1422 | 1427 | ||
| 1423 | /// Same as `readlink` except `file_path` is null-terminated. | 1428 | /// Same as `readlink` except `file_path` is null-terminated. |
| 1424 | pub fn readlinkC(file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 1429 | pub 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 | } |
| 1444 | 1449 | ||
| 1445 | pub fn readlinkatC(dirfd: fd_t, file_path: [*]const u8, out_buffer: []u8) ReadLinkError![]u8 { | 1450 | pub 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 | } |
| 2130 | 2135 | ||
| 2131 | /// Same as `inotify_add_watch` except pathname is null-terminated. | 2136 | /// Same as `inotify_add_watch` except pathname is null-terminated. |
| 2132 | pub fn inotify_add_watchC(inotify_fd: i32, pathname: [*]const u8, mask: u32) INotifyAddWatchError!i32 { | 2137 | pub 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 | } |
| 2287 | 2292 | ||
| 2288 | /// Same as `access` except `path` is null-terminated. | 2293 | /// Same as `access` except `path` is null-terminated. |
| 2289 | pub fn accessC(path: [*]const u8, mode: u32) AccessError!void { | 2294 | pub 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`. |
| 2316 | pub fn accessW(path: [*]const u16, mode: u32) windows.GetFileAttributesError!void { | 2321 | pub 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 | } |
| 2381 | 2386 | ||
| 2382 | pub fn sysctlbynameC( | 2387 | pub 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 | } |
| 2563 | 2568 | ||
| 2564 | /// Same as `realpath` except `pathname` is null-terminated. | 2569 | /// Same as `realpath` except `pathname` is null-terminated. |
| 2565 | pub fn realpathC(pathname: [*]const u8, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 2570 | pub 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); |
| 2573 | 2578 | ||
| 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; |
| 2576 | 2581 | ||
| 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 | } |
| 2594 | 2599 | ||
| 2595 | /// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded. | 2600 | /// Same as `realpath` except `pathname` is null-terminated and UTF16LE-encoded. |
| 2596 | pub fn realpathW(pathname: [*]const u16, out_buffer: *[MAX_PATH_BYTES]u8) RealPathError![]u8 { | 2601 | pub 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 { |
| 2748 | 2753 | ||
| 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/287 | 2755 | /// TODO https://github.com/ziglang/zig/issues/287 |
| 2751 | pub fn toPosixPath(file_path: []const u8) ![PATH_MAX]u8 { | 2756 | pub 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 byte | 2758 | // >= 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; |
| 2854 | pub fn gethostname(name_buffer: *[HOST_NAME_MAX]u8) GetHostNameError![]u8 { | 2859 | pub 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 this | 2864 | 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 | }; |
| 1369 | 1369 |
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 | } |
| 57 | 57 | ||
| 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.11 | 61 | // 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 | } |
| 65 | 65 | ||
| 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 { |
| 19 | pub const iovec_t = iovec; | 19 | pub const iovec_t = iovec; |
| 20 | pub const ciovec_t = iovec_const; | 20 | pub const ciovec_t = iovec_const; |
| 21 | 21 | ||
| 22 | pub extern "wasi_unstable" fn args_get(argv: [*][*]u8, argv_buf: [*]u8) errno_t; | 22 | pub extern "wasi_unstable" fn args_get(argv: [*][*:0]u8, argv_buf: [*]u8) errno_t; |
| 23 | pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; | 23 | pub extern "wasi_unstable" fn args_sizes_get(argc: *usize, argv_buf_size: *usize) errno_t; |
| 24 | 24 | ||
| 25 | pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t; | 25 | pub extern "wasi_unstable" fn clock_res_get(clock_id: clockid_t, resolution: *timestamp_t) errno_t; |
| 26 | pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t; | 26 | pub extern "wasi_unstable" fn clock_time_get(clock_id: clockid_t, precision: timestamp_t, timestamp: *timestamp_t) errno_t; |
| 27 | 27 | ||
| 28 | pub extern "wasi_unstable" fn environ_get(environ: [*]?[*]u8, environ_buf: [*]u8) errno_t; | 28 | pub extern "wasi_unstable" fn environ_get(environ: [*]?[*:0]u8, environ_buf: [*]u8) errno_t; |
| 29 | pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t; | 29 | pub extern "wasi_unstable" fn environ_sizes_get(environ_count: *usize, environ_buf_size: *usize) errno_t; |
| 30 | 30 | ||
| 31 | pub extern "wasi_unstable" fn fd_advise(fd: fd_t, offset: filesize_t, len: filesize_t, advice: advice_t) errno_t; | 31 | pub 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 | }; |
| 193 | 193 | ||
| 194 | pub fn FindFirstFile(dir_path: []const u8, find_file_data: *WIN32_FIND_DATAW) FindFirstFileError!HANDLE { | 194 | pub 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); |
| 197 | 197 | ||
| 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 | } |
| 921 | 921 | ||
| 922 | pub fn cStrToPrefixedFileW(s: [*]const u8) ![PATH_MAX_WIDE + 1]u16 { | 922 | pub 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 | } |
| 925 | 925 | ||
| 926 | pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE + 1]u16 { | 926 | pub fn sliceToPrefixedFileW(s: []const u8) ![PATH_MAX_WIDE:0]u16 { |
| 927 | return sliceToPrefixedSuffixedFileW(s, [_]u16{0}); | 927 | return sliceToPrefixedSuffixedFileW(s, &[_]u16{}); |
| 928 | } | 928 | } |
| 929 | 929 | ||
| 930 | /// Assumes an absolute path. | 930 | /// Assumes an absolute path. |
| 931 | pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE + 1]u16 { | 931 | pub fn wToPrefixedFileW(s: []const u16) ![PATH_MAX_WIDE:0]u16 { |
| 932 | // TODO https://github.com/ziglang/zig/issues/2765 | 932 | // 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; |
| 934 | 934 | ||
| 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 { |
| 945 | 945 | ||
| 946 | } | 946 | } |
| 947 | 947 | ||
| 948 | pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len]u16 { | 948 | pub fn sliceToPrefixedSuffixedFileW(s: []const u8, comptime suffix: []const u16) ![PATH_MAX_WIDE + suffix.len:0]u16 { |
| 949 | // TODO https://github.com/ziglang/zig/issues/2765 | 949 | // 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 of | 951 | // > 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 | } |
| 973 | 974 |
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 { |
| 77 | 77 | ||
| 78 | // TODO: Verify that the documentation is incorrect | 78 | // TODO: Verify that the documentation is incorrect |
| 79 | // https://github.com/WebAssembly/WASI/issues/27 | 79 | // 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 | } |
| 399 | 399 | ||
| 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); |
| 402 | 402 | ||
| 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 | } |
| 474 | 474 | ||
| 475 | test "windows arg parsing" { | 475 | test "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" }); |
| 482 | 482 | ||
| 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 | } |
| 67 | 67 | ||
| 68 | extern fn strerror(errnum: c_int) [*]const u8 { | 68 | extern fn strerror(errnum: c_int) [*]const u8 { |
| 69 | return c"TODO strerror implementation"; | 69 | return "TODO strerror implementation"; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | test "strncmp" { | 72 | test "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 | } |
| 78 | 78 | ||
| 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); |
| 127 | 127 | ||
| 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]; |
| 132 | 132 | ||
| 133 | if (builtin.os == .linux) { | 133 | if (builtin.os == .linux) { |
| 134 | // Find the beginning of the auxiliary vector | 134 | // 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 | } |
| 170 | 170 | ||
| 171 | fn callMainWithArgs(argc: usize, argv: [*][*]u8, envp: [][*]u8) u8 { | 171 | fn 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; |
| 174 | 174 | ||
| ... | @@ -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 | } |
| 179 | 179 | ||
| 180 | extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 { | 180 | extern 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 | } |
| 186 | 186 |
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; |
| 3 | const valgrind = std.valgrind; | 3 | const valgrind = std.valgrind; |
| 4 | 4 | ||
| 5 | pub const MemCheckClientRequest = extern enum { | 5 | pub 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 | }; |
| 1532 | 1532 | ||
| 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, |
| 1538 | 1538 | ||
| 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 | }; |
| 1554 | 1554 | ||
| 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, | ||
| 1560 | 1566 | ||
| 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/1107 | 1582 | // 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 | }, |
| 1590 | 1601 | ||
| 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 | }, |
| 1595 | 1610 | ||
| 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 caller | 1088 | .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 { |
| 1138 | 1138 | ||
| 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 |
| 1531 | 1531 | ||
| 1532 | // anon container literal | 1532 | // 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 | } |
| 1537 | 1537 | ||
| ... | @@ -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 | } |
| 2248 | 2248 | ||
| 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 | } |
| 2363 | 2306 | ||
| 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 | } |
| 2366 | 2366 | ||
| ... | @@ -2459,10 +2459,21 @@ const AnnotatedParamList = struct { | ... | @@ -2459,10 +2459,21 @@ const AnnotatedParamList = struct { |
| 2459 | fn parseArrayTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 2459 | fn 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); |
| 2463 | 2469 | ||
| 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 | else | 2477 | 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 | }; |
| 2475 | 2487 | ||
| ... | @@ -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 | /// / PTRUNKNOWN | 2501 | /// / PTRUNKNOWN |
| 2490 | /// / PTRC | 2502 | /// / PTRC |
| 2491 | fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { | 2503 | fn parsePtrTypeStart(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node { |
| 2492 | const token = eatAnnotatedToken(it, .Asterisk) orelse | 2504 | if (eatToken(it, .Asterisk)) |asterisk| { |
| 2493 | eatAnnotatedToken(it, .AsteriskAsterisk) orelse | 2505 | const sentinel = if (eatToken(it, .Colon)) |_| |
| 2494 | eatAnnotatedToken(it, .BracketStarBracket) orelse | 2506 | try expectNode(arena, it, tree, parseExpr, AstError{ |
| 2495 | eatAnnotatedToken(it, .BracketStarCBracket) orelse | 2507 | .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 | } | ||
| 2497 | 2519 | ||
| 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 | }; | ||
| 2512 | 2527 | ||
| 2513 | // Special case for **, which is its own token | 2528 | // 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 caller | 2533 | .rhs = undefined, // set by caller |
| 2528 | }; | 2534 | }; |
| 2529 | node.rhs = &child.base; | 2535 | node.rhs = &child.base; |
| 2530 | } | ||
| 2531 | 2536 | ||
| 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 | } |
| 2534 | 2575 | ||
| 2535 | /// ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE | 2576 | /// 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 | \\ \\three | 1726 | \\ \\three |
| 1725 | \\ ; | 1727 | \\ ; |
| 1726 | \\ const s2 = | ||
| 1727 | \\ c\\one | ||
| 1728 | \\ c\\two) | ||
| 1729 | \\ c\\three | ||
| 1730 | \\ ; | ||
| 1731 | \\ const s3 = // hi | 1728 | \\ const s3 = // hi |
| 1732 | \\ \\one | 1729 | \\ \\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( |
| 418 | 418 | ||
| 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); // allowzero | 443 | 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 | }, |
| 501 | 517 | ||
| 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()); | ||
| 505 | 524 | ||
| 506 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ | 525 | try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [ |
| 507 | 526 | ||
| ... | @@ -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 | }; |
| 408 | 400 | ||
| 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 | }, |
| 571 | 561 | ||
| 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 | \\[*]u8 | 1321 | \\[*]u8 |
| 1389 | \\[*c]u8 | 1322 | \\[*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 | }; |
| 709 | 709 | ||
| 710 | pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation; | 710 | pub extern fn ZigClangSourceManager_getSpellingLoc(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation; |
| 711 | pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8; | 711 | pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*:0]const u8; |
| 712 | pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | 712 | pub extern fn ZigClangSourceManager_getSpellingLineNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; |
| 713 | pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; | 713 | pub extern fn ZigClangSourceManager_getSpellingColumnNumber(self: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint; |
| 714 | pub extern fn ZigClangSourceManager_getCharacterData(self: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8; | 714 | pub 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 |
| 746 | pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; | 746 | pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass; |
| 747 | pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType; | 747 | pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType; |
| 748 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; | 748 | pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool; |
| 749 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8; | 749 | pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*:0]const u8; |
| 750 | pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; | 750 | pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation; |
| 751 | pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; | 751 | pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) ZigClangStmtClass; |
| 752 | pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool; | 752 | pub 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; |
| 905 | 905 | ||
| 906 | pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind; | 906 | pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind; |
| 907 | pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8; | 907 | pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*:0]const u8; |
| 908 | 908 | ||
| 909 | pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt; | 909 | pub const ZigClangCompoundStmt_const_body_iterator = [*c]const *struct_ZigClangStmt; |
| 910 | 910 |
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 | } |
| 407 | 407 | ||
| 408 | pub fn renderStoreUntyped( | 408 | pub 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/508 | 491 | // 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 { |
| 501 | 501 | ||
| 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 | }); |
| 1565 | 1565 | ||
| 1566 | const ret_stmt_block = try irb.createBasicBlock(scope, c"RetStmt"); | 1566 | const ret_stmt_block = try irb.createBasicBlock(scope, "RetStmt"); |
| 1567 | 1567 | ||
| 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(); |
| 2530 | 2530 | ||
| 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); |
| 2534 | 2534 |
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 { |
| 55 | 55 | ||
| 56 | // even though we're calling LLD as a library it thinks the first | 56 | // even though we're calling LLD as a library it thinks the first |
| 57 | // argument is its own exe name | 57 | // argument is its own exe name |
| 58 | try ctx.args.append(c"lld"); | 58 | try ctx.args.append("lld"); |
| 59 | 59 | ||
| 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"); |
| 149 | 149 | ||
| 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 | //} |
| 172 | 172 | ||
| 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()); |
| 175 | 175 | ||
| 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 | //} |
| 214 | 214 | ||
| 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); |
| 218 | 218 | ||
| 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); |
| 221 | 221 | ||
| 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 dep | 272 | // 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 | } |
| 294 | 294 | ||
| ... | @@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void { | ... | @@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void { |
| 299 | } | 299 | } |
| 300 | 300 | ||
| 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 | } |
| 304 | 304 | ||
| 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"); |
| 308 | 308 | ||
| 309 | try ctx.args.append(c"--image-base=0x10000000"); | 309 | try ctx.args.append("--image-base=0x10000000"); |
| 310 | } | 310 | } |
| 311 | } | 311 | } |
| 312 | 312 | ||
| ... | @@ -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 | } |
| 318 | 318 | ||
| 319 | fn constructLinkerArgsCoff(ctx: *Context) !void { | 319 | fn constructLinkerArgsCoff(ctx: *Context) !void { |
| 320 | try ctx.args.append(c"-NOLOGO"); | 320 | try ctx.args.append("-NOLOGO"); |
| 321 | 321 | ||
| 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 | } |
| 325 | 325 | ||
| 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 | } |
| 332 | 332 | ||
| 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 | } |
| 338 | 338 | ||
| 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 { |
| 367 | 367 | ||
| 368 | // Visual C++ 2015 Conformance Changes | 368 | // Visual C++ 2015 Conformance Changes |
| 369 | // https://msdn.microsoft.com/en-us/library/bb531344.aspx | 369 | // 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"); |
| 371 | 371 | ||
| 372 | // msvcrt depends on kernel32 | 372 | // 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 | // TODO | 378 | // 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 | } |
| 386 | 386 | ||
| 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 | } |
| 390 | 390 | ||
| 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 | } |
| 464 | 464 | ||
| 465 | fn constructLinkerArgsMachO(ctx: *Context) !void { | 465 | fn constructLinkerArgsMachO(ctx: *Context) !void { |
| 466 | try ctx.args.append(c"-demangle"); | 466 | try ctx.args.append("-demangle"); |
| 467 | 467 | ||
| 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 | } |
| 471 | 471 | ||
| 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 | } |
| 479 | 479 | ||
| 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 | //} |
| 505 | 505 | ||
| 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 { |
| 512 | 512 | ||
| 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); |
| 521 | 521 | ||
| 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 | } |
| 529 | 529 | ||
| 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()); |
| 532 | 532 | ||
| 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); |
| 538 | 538 | ||
| 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 arm64 | 556 | // 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 needed | 563 | .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 documented | 589 | // 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 libSystem | 591 | // 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 | } |
| 607 | 607 | ||
| 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; |
| 83 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; | 83 | pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext; |
| 84 | 84 | ||
| 85 | pub const AddGlobal = LLVMAddGlobal; | 85 | pub const AddGlobal = LLVMAddGlobal; |
| 86 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value; | 86 | extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*:0]const u8) ?*Value; |
| 87 | 87 | ||
| 88 | pub const ConstStringInContext = LLVMConstStringInContext; | 88 | pub const ConstStringInContext = LLVMConstStringInContext; |
| 89 | extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value; | 89 | extern fn LLVMConstStringInContext(C: *Context, Str: [*:0]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value; |
| 90 | 90 | ||
| 91 | pub const ConstInt = LLVMConstInt; | 91 | pub const ConstInt = LLVMConstInt; |
| 92 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value; | 92 | extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value; |
| 93 | 93 | ||
| 94 | pub const BuildLoad = LLVMBuildLoad; | 94 | pub const BuildLoad = LLVMBuildLoad; |
| 95 | extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value; | 95 | extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*:0]const u8) ?*Value; |
| 96 | 96 | ||
| 97 | pub const ConstNull = LLVMConstNull; | 97 | pub const ConstNull = LLVMConstNull; |
| 98 | extern fn LLVMConstNull(Ty: *Type) ?*Value; | 98 | extern fn LLVMConstNull(Ty: *Type) ?*Value; |
| ... | @@ -110,24 +110,24 @@ pub const CreateEnumAttribute = LLVMCreateEnumAttribute; | ... | @@ -110,24 +110,24 @@ pub const CreateEnumAttribute = LLVMCreateEnumAttribute; |
| 110 | extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute; | 110 | extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute; |
| 111 | 111 | ||
| 112 | pub const AddFunction = LLVMAddFunction; | 112 | pub const AddFunction = LLVMAddFunction; |
| 113 | extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value; | 113 | extern fn LLVMAddFunction(M: *Module, Name: [*:0]const u8, FunctionTy: *Type) ?*Value; |
| 114 | 114 | ||
| 115 | pub const CreateCompileUnit = ZigLLVMCreateCompileUnit; | 115 | pub const CreateCompileUnit = ZigLLVMCreateCompileUnit; |
| 116 | extern fn ZigLLVMCreateCompileUnit( | 116 | extern 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; |
| 128 | 128 | ||
| 129 | pub const CreateFile = ZigLLVMCreateFile; | 129 | pub const CreateFile = ZigLLVMCreateFile; |
| 130 | extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile; | 130 | extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*:0]const u8, directory: [*:0]const u8) ?*DIFile; |
| 131 | 131 | ||
| 132 | pub const ArrayType = LLVMArrayType; | 132 | pub const ArrayType = LLVMArrayType; |
| 133 | extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type; | 133 | extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type; |
| ... | @@ -145,7 +145,7 @@ pub const IntTypeInContext = LLVMIntTypeInContext; | ... | @@ -145,7 +145,7 @@ pub const IntTypeInContext = LLVMIntTypeInContext; |
| 145 | extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type; | 145 | extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type; |
| 146 | 146 | ||
| 147 | pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext; | 147 | pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext; |
| 148 | extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module; | 148 | extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*:0]const u8, C: *Context) ?*Module; |
| 149 | 149 | ||
| 150 | pub const VoidTypeInContext = LLVMVoidTypeInContext; | 150 | pub const VoidTypeInContext = LLVMVoidTypeInContext; |
| 151 | extern fn LLVMVoidTypeInContext(C: *Context) ?*Type; | 151 | extern fn LLVMVoidTypeInContext(C: *Context) ?*Type; |
| ... | @@ -157,7 +157,7 @@ pub const ContextDispose = LLVMContextDispose; | ... | @@ -157,7 +157,7 @@ pub const ContextDispose = LLVMContextDispose; |
| 157 | extern fn LLVMContextDispose(C: *Context) void; | 157 | extern fn LLVMContextDispose(C: *Context) void; |
| 158 | 158 | ||
| 159 | pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData; | 159 | pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData; |
| 160 | extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8; | 160 | extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*:0]u8; |
| 161 | 161 | ||
| 162 | pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; | 162 | pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout; |
| 163 | extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData; | 163 | extern 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; |
| 165 | pub const CreateTargetMachine = ZigLLVMCreateTargetMachine; | 165 | pub const CreateTargetMachine = ZigLLVMCreateTargetMachine; |
| 166 | extern fn ZigLLVMCreateTargetMachine( | 166 | extern 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; |
| 176 | 176 | ||
| 177 | pub const GetHostCPUName = LLVMGetHostCPUName; | 177 | pub const GetHostCPUName = LLVMGetHostCPUName; |
| 178 | extern fn LLVMGetHostCPUName() ?[*]u8; | 178 | extern fn LLVMGetHostCPUName() ?[*:0]u8; |
| 179 | 179 | ||
| 180 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; | 180 | pub const GetNativeFeatures = ZigLLVMGetNativeFeatures; |
| 181 | extern fn ZigLLVMGetNativeFeatures() ?[*]u8; | 181 | extern fn ZigLLVMGetNativeFeatures() ?[*:0]u8; |
| 182 | 182 | ||
| 183 | pub const GetElementType = LLVMGetElementType; | 183 | pub const GetElementType = LLVMGetElementType; |
| 184 | extern fn LLVMGetElementType(Ty: *Type) *Type; | 184 | extern fn LLVMGetElementType(Ty: *Type) *Type; |
| ... | @@ -190,16 +190,16 @@ pub const BuildStore = LLVMBuildStore; | ... | @@ -190,16 +190,16 @@ pub const BuildStore = LLVMBuildStore; |
| 190 | extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value; | 190 | extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value; |
| 191 | 191 | ||
| 192 | pub const BuildAlloca = LLVMBuildAlloca; | 192 | pub const BuildAlloca = LLVMBuildAlloca; |
| 193 | extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value; | 193 | extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*:0]const u8) ?*Value; |
| 194 | 194 | ||
| 195 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; | 195 | pub const ConstInBoundsGEP = LLVMConstInBoundsGEP; |
| 196 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value; | 196 | pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value; |
| 197 | 197 | ||
| 198 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; | 198 | pub const GetTargetFromTriple = LLVMGetTargetFromTriple; |
| 199 | extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool; | 199 | extern fn LLVMGetTargetFromTriple(Triple: [*:0]const u8, T: **Target, ErrorMessage: ?*[*:0]u8) Bool; |
| 200 | 200 | ||
| 201 | pub const VerifyModule = LLVMVerifyModule; | 201 | pub const VerifyModule = LLVMVerifyModule; |
| 202 | extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool; | 202 | extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*:0]u8) Bool; |
| 203 | 203 | ||
| 204 | pub const GetInsertBlock = LLVMGetInsertBlock; | 204 | pub const GetInsertBlock = LLVMGetInsertBlock; |
| 205 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; | 205 | extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock; |
| ... | @@ -216,7 +216,7 @@ pub const GetParam = LLVMGetParam; | ... | @@ -216,7 +216,7 @@ pub const GetParam = LLVMGetParam; |
| 216 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; | 216 | extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value; |
| 217 | 217 | ||
| 218 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; | 218 | pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext; |
| 219 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock; | 219 | extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*:0]const u8) ?*BasicBlock; |
| 220 | 220 | ||
| 221 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; | 221 | pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd; |
| 222 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; | 222 | extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void; |
| ... | @@ -278,14 +278,14 @@ pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; | ... | @@ -278,14 +278,14 @@ pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile; |
| 278 | extern fn ZigLLVMTargetMachineEmitToFile( | 278 | extern 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; |
| 287 | 287 | ||
| 288 | pub const BuildCall = ZigLLVMBuildCall; | 288 | pub const BuildCall = ZigLLVMBuildCall; |
| 289 | extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value; | 289 | extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*:0]const u8) ?*Value; |
| 290 | 290 | ||
| 291 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; | 291 | pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage; |
src-self-hosted/stage1.zig+3-3| ... | @@ -27,7 +27,7 @@ comptime { | ... | @@ -27,7 +27,7 @@ comptime { |
| 27 | // ABI warning | 27 | // ABI warning |
| 28 | export fn stage2_zen(ptr: *[*]const u8, len: *usize) void { | 28 | export 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 | } |
| 33 | 33 | ||
| ... | @@ -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 { |
| 144 | 144 | ||
| 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. |
| 147 | export fn stage2_fmt(argc: c_int, argv: [*]const [*]const u8) c_int { | 147 | export 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 | } |
| 158 | 158 | ||
| 159 | fn fmtMain(argc: c_int, argv: [*]const [*]const u8) !void { | 159 | fn 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 | } |
| 114 | 114 | ||
| 115 | /// Convert a null-terminated C string to a slice allocated in the arena | 115 | /// 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 | } |
| 119 | 119 | ||
| ... | @@ -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; |
| 698 | 698 | ||
| 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] = '"'; |
| 704 | 703 | ||
| 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 { |
| 172 | 172 | ||
| 173 | pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target { | 173 | pub 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 | }; |
| 105 | 109 | ||
| 106 | enum OutType { | 110 | enum 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; |
| 352 | 353 | ||
| 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 null | 357 | IrInstruction *align_inst; // can be null |
| 356 | 358 | ||
| ... | @@ -363,6 +365,7 @@ struct LazyValuePtrType { | ... | @@ -363,6 +365,7 @@ struct LazyValuePtrType { |
| 363 | LazyValue base; | 365 | LazyValue base; |
| 364 | 366 | ||
| 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 null | 370 | IrInstruction *align_inst; // can be null |
| 368 | 371 | ||
| ... | @@ -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 | }; |
| 602 | 606 | ||
| 603 | enum CallingConvention { | 607 | enum CallingConvention { |
| ... | @@ -818,6 +822,7 @@ struct AstNodePrefixOpExpr { | ... | @@ -818,6 +822,7 @@ struct AstNodePrefixOpExpr { |
| 818 | 822 | ||
| 819 | struct AstNodePointerType { | 823 | struct 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 | }; |
| 829 | 834 | ||
| 830 | struct AstNodeInferredArrayType { | 835 | struct AstNodeInferredArrayType { |
| 836 | AstNode *sentinel; // can be null | ||
| 831 | AstNode *child_type; | 837 | AstNode *child_type; |
| 832 | }; | 838 | }; |
| 833 | 839 | ||
| 834 | struct AstNodeArrayType { | 840 | struct 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 { |
| 997 | 1004 | ||
| 998 | struct AstNodeStringLiteral { | 1005 | struct AstNodeStringLiteral { |
| 999 | Buf *buf; | 1006 | Buf *buf; |
| 1000 | bool c; | ||
| 1001 | }; | 1007 | }; |
| 1002 | 1008 | ||
| 1003 | struct AstNodeCharLiteral { | 1009 | struct 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; |
| 1206 | 1212 | ||
| 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 alignment | 1219 | uint32_t explicit_alignment; // 0 means use ABI alignment |
| 1209 | 1220 | ||
| ... | @@ -1231,6 +1242,7 @@ struct ZigTypeFloat { | ... | @@ -1231,6 +1242,7 @@ struct ZigTypeFloat { |
| 1231 | struct ZigTypeArray { | 1242 | struct ZigTypeArray { |
| 1232 | ZigType *child_type; | 1243 | ZigType *child_type; |
| 1233 | uint64_t len; | 1244 | uint64_t len; |
| 1245 | ConstExprValue *sentinel; | ||
| 1234 | }; | 1246 | }; |
| 1235 | 1247 | ||
| 1236 | struct TypeStructField { | 1248 | struct TypeStructField { |
| ... | @@ -1756,8 +1768,10 @@ struct TypeId { | ... | @@ -1756,8 +1768,10 @@ struct TypeId { |
| 1756 | 1768 | ||
| 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; |
| 1763 | 1777 | ||
| ... | @@ -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; | ||
| 1953 | 1970 | ||
| 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; |
| 2028 | 2045 | ||
| 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]; |
| 2031 | 2049 | ||
| ... | @@ -2982,12 +3000,14 @@ struct IrInstructionArrayType { | ... | @@ -2982,12 +3000,14 @@ struct IrInstructionArrayType { |
| 2982 | IrInstruction base; | 3000 | IrInstruction base; |
| 2983 | 3001 | ||
| 2984 | IrInstruction *size; | 3002 | IrInstruction *size; |
| 3003 | IrInstruction *sentinel; | ||
| 2985 | IrInstruction *child_type; | 3004 | IrInstruction *child_type; |
| 2986 | }; | 3005 | }; |
| 2987 | 3006 | ||
| 2988 | struct IrInstructionPtrType { | 3007 | struct IrInstructionPtrType { |
| 2989 | IrInstruction base; | 3008 | IrInstruction base; |
| 2990 | 3009 | ||
| 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 { |
| 3007 | struct IrInstructionSliceType { | 3027 | struct IrInstructionSliceType { |
| 3008 | IrInstruction base; | 3028 | IrInstruction base; |
| 3009 | 3029 | ||
| 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 | } |
| 454 | 454 | ||
| 455 | static 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 | |||
| 467 | ZigType *get_fn_frame_type(CodeGen *g, ZigFn *fn) { | 455 | ZigType *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 | } |
| 485 | 473 | ||
| 474 | static 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 | |||
| 486 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, bool is_const, | 511 | ZigType *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; | ||
| 525 | 553 | ||
| 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 |
| 537 | 565 | ||
| 538 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); | 566 | ZigType *entry = new_type_table_entry(ZigTypeIdPointer); |
| 539 | 567 | ||
| 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 | |||
| 590 | 597 | ||
| 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); | ||
| 618 | 628 | ||
| 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 | } |
| 634 | 644 | ||
| 635 | ZigType *get_pointer_to_type(CodeGen *g, ZigType *child_type, bool is_const) { | 645 | ZigType *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 | } |
| 639 | 649 | ||
| 640 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { | 650 | ZigType *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 | } |
| 752 | 762 | ||
| 753 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { | 763 | ZigType *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); |
| 766 | 778 | ||
| 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 | } | ||
| 769 | 793 | ||
| 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; |
| 773 | 797 | ||
| 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; | ||
| 776 | 801 | ||
| 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) { |
| 789 | 814 | ||
| 790 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); | 815 | ZigType *entry = new_type_table_entry(ZigTypeIdStruct); |
| 791 | 816 | ||
| 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); | ||
| 796 | 825 | ||
| 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 | } |
| 834 | 863 | ||
| 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 * |
| 1150 | Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) { | 1163 | Error 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 | } |
| 5547 | 5564 | ||
| 5565 | ConstExprValue *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 | |||
| 5548 | ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) { | 5577 | ReqCompTime 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 | } |
| 5614 | 5646 | ||
| 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 | |||
| 5623 | ConstExprValue *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 | |||
| 5629 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) { | ||
| 5630 | // first we build the underlying array | 5647 | // 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 optimization | 5651 | 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); | ||
| 5647 | 5653 | ||
| 5648 | // then make the pointer point to it | 5654 | // 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 | } |
| 5658 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) { | 5663 | |
| 5664 | ConstExprValue *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 | } |
| 5663 | 5669 | ||
| ... | @@ -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 | } |
| 5709 | 5715 | ||
| 5716 | void 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 | |||
| 5722 | ConstExprValue *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 | |||
| 5710 | void init_const_float(ConstExprValue *const_val, ZigType *type, double value) { | 5728 | void 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) { |
| 6069 | 6087 | ||
| 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 | } |
| 6074 | 6092 | ||
| 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 | } |
| 6282 | 6300 | ||
| 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) { |
| 6441 | bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) { | 6459 | bool 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 | } |
| 6537 | 6551 | ||
| 6538 | bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) { | 6552 | bool 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 |
| 7761 | 7792 | ||
| 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) { |
| 8646 | 8679 | ||
| 8647 | ZigType *elem_type = type->data.array.child_type; | 8680 | ZigType *elem_type = type->data.array.child_type; |
| 8648 | 8681 | ||
| 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/1424 | 8684 | // 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); |
| 8651 | 8686 | ||
| 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); |
| 8654 | 8689 | ||
| 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 | } |
| 8658 | 8693 | ||
| 8659 | static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) { | 8694 | static 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 | |||
| 9183 | void 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, |
| 24 | ZigType *get_pointer_to_type_extra2(CodeGen *g, ZigType *child_type, | 24 | ZigType *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); | ||
| 28 | uint64_t type_size(CodeGen *g, ZigType *type_entry); | 29 | uint64_t type_size(CodeGen *g, ZigType *type_entry); |
| 29 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); | 30 | uint64_t type_size_bits(CodeGen *g, ZigType *type_entry); |
| 30 | ZigType *get_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits); | 31 | ZigType *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); |
| 33 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); | 34 | ZigType *get_c_int_type(CodeGen *g, CIntType c_int_type); |
| 34 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); | 35 | ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id); |
| 35 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type); | 36 | ZigType *get_optional_type(CodeGen *g, ZigType *child_type); |
| 36 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size); | 37 | ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, ConstExprValue *sentinel); |
| 37 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); | 38 | ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type); |
| 38 | ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind, | 39 | ZigType *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); |
| 126 | void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str); | 127 | void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str); |
| 127 | ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); | 128 | ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str); |
| 128 | 129 | ||
| 129 | void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str); | ||
| 130 | ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str); | ||
| 131 | |||
| 132 | void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint); | 130 | void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint); |
| 133 | ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint); | 131 | ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint); |
| 134 | 132 | ||
| ... | @@ -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 |
| 176 | void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end); | 174 | void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end); |
| 177 | ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); | 175 | ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end); |
| 178 | 176 | ||
| 177 | void init_const_null(ConstExprValue *const_val, ZigType *type); | ||
| 178 | ConstExprValue *create_const_null(ZigType *type); | ||
| 179 | |||
| 179 | ConstExprValue *create_const_vals(size_t count); | 180 | ConstExprValue *create_const_vals(size_t count); |
| 180 | ConstExprValue **alloc_const_vals_ptrs(size_t count); | 181 | ConstExprValue **alloc_const_vals_ptrs(size_t count); |
| 181 | ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count); | 182 | ConstExprValue **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); |
| 276 | Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str, | 277 | Error 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); |
| 278 | 279 | ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry); | |
| 279 | #endif | 280 | #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) { |
| 950 | 950 | ||
| 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); |
| 954 | 954 | ||
| 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; |
| 2786 | 2786 | ||
| 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; |
| 2797 | 2789 | ||
| ... | @@ -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; |
| 2849 | 2841 | ||
| 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); |
| 3755 | 3754 | ||
| 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 | } |
| 3775 | 3775 | ||
| 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 pointer | 6640 | 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)); |
| 7470 | 7485 | ||
| 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); |
| 8630 | 8645 | ||
| 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(); |
| 9068 | 9088 | ||
| 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); |
| 9073 | 9093 | ||
| ... | @@ -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); |
| 9093 | 9113 | ||
| 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); |
| 9097 | 9117 | ||
| 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 | }; |
| 70 | 75 | ||
| 71 | struct ConstCastOnly; | 76 | struct ConstCastOnly; |
| ... | @@ -87,7 +92,11 @@ struct ConstCastErrUnionErrSetMismatch; | ... | @@ -87,7 +92,11 @@ struct ConstCastErrUnionErrSetMismatch; |
| 87 | struct ConstCastErrUnionPayloadMismatch; | 92 | struct ConstCastErrUnionPayloadMismatch; |
| 88 | struct ConstCastErrSetMismatch; | 93 | struct ConstCastErrSetMismatch; |
| 89 | struct ConstCastTypeMismatch; | 94 | struct ConstCastTypeMismatch; |
| 95 | struct ConstCastArrayMismatch; | ||
| 90 | struct ConstCastBadAllowsZero; | 96 | struct ConstCastBadAllowsZero; |
| 97 | struct ConstCastBadNullTermArrays; | ||
| 98 | struct ConstCastBadCV; | ||
| 99 | struct ConstCastPtrSentinel; | ||
| 91 | 100 | ||
| 92 | struct ConstCastOnly { | 101 | struct 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 | }; |
| 109 | 122 | ||
| ... | @@ -130,6 +143,12 @@ struct ConstCastSliceMismatch { | ... | @@ -130,6 +143,12 @@ struct ConstCastSliceMismatch { |
| 130 | ZigType *actual_child; | 143 | ZigType *actual_child; |
| 131 | }; | 144 | }; |
| 132 | 145 | ||
| 146 | struct ConstCastArrayMismatch { | ||
| 147 | ConstCastOnly child; | ||
| 148 | ZigType *wanted_child; | ||
| 149 | ZigType *actual_child; | ||
| 150 | }; | ||
| 151 | |||
| 133 | struct ConstCastErrUnionErrSetMismatch { | 152 | struct 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 | }; |
| 153 | 172 | ||
| 173 | struct ConstCastBadNullTermArrays { | ||
| 174 | ConstCastOnly child; | ||
| 175 | ZigType *wanted_type; | ||
| 176 | ZigType *actual_type; | ||
| 177 | }; | ||
| 178 | |||
| 179 | struct ConstCastBadCV { | ||
| 180 | ZigType *wanted_type; | ||
| 181 | ZigType *actual_type; | ||
| 182 | }; | ||
| 183 | |||
| 184 | struct ConstCastPtrSentinel { | ||
| 185 | ZigType *wanted_type; | ||
| 186 | ZigType *actual_type; | ||
| 187 | }; | ||
| 154 | 188 | ||
| 155 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); | 189 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); |
| 156 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, | 190 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, |
| 157 | ResultLoc *result_loc); | 191 | ResultLoc *result_loc); |
| 158 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type); | 192 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type); |
| 193 | static IrInstruction *ir_implicit_cast2(IrAnalyze *ira, IrInstruction *value_source_instr, | ||
| 194 | IrInstruction *value, ZigType *expected_type); | ||
| 159 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, | 195 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, |
| 160 | ResultLoc *result_loc); | 196 | ResultLoc *result_loc); |
| 161 | static ErrorMsg *exec_add_error_node(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, Buf *msg); | 197 | static 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) { |
| 282 | 319 | ||
| 283 | // This function returns true when you can change the type of a ConstExprValue and the | 320 | // This function returns true when you can change the type of a ConstExprValue and the |
| 284 | // value remains meaningful. | 321 | // value remains meaningful. |
| 285 | static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { | 322 | static 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; |
| 288 | 325 | ||
| 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; |
| 291 | 328 | ||
| 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; |
| 294 | 331 | ||
| 295 | if (a->id != b->id) | 332 | if (expected->id != actual->id) |
| 296 | return false; | 333 | return false; |
| 297 | 334 | ||
| 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 | } |
| 1301 | 1342 | ||
| 1302 | static 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 | |||
| 1308 | static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id, | 1343 | static 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_ |
| 1544 | 1579 | ||
| 1545 | static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1580 | static 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; |
| 1558 | 1595 | ||
| 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); |
| 1561 | 1599 | ||
| ... | @@ -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 | } |
| 1773 | 1811 | ||
| 1774 | static IrInstruction *ir_build_array_type(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *size, | 1812 | static 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; |
| 1780 | 1819 | ||
| 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); |
| 1783 | 1823 | ||
| 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 |
| 1794 | 1834 | ||
| 1795 | return &instruction->base; | 1835 | return &instruction->base; |
| 1796 | } | 1836 | } |
| 1837 | |||
| 1797 | static IrInstruction *ir_build_slice_type(IrBuilder *irb, Scope *scope, AstNode *source_node, | 1838 | static 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; |
| 1806 | 1849 | ||
| 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); | ||
| 1809 | 1853 | ||
| 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) { |
| 6043 | 6087 | ||
| 6044 | static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) { | 6088 | static 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; |
| 6052 | 6099 | ||
| 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 | } |
| 6095 | 6151 | ||
| 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 | } |
| 6099 | 6155 | ||
| 6100 | static IrInstruction *ir_gen_catch_unreachable(IrBuilder *irb, Scope *scope, AstNode *source_node, | 6156 | static 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 |
| 6917 | static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) { | 6982 | static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) { |
| 6918 | assert(node->type == NodeTypeStringLiteral); | 6983 | assert(node->type == NodeTypeStringLiteral); |
| 6919 | 6984 | ||
| 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 | } |
| 6926 | 6987 | ||
| 6927 | static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *node) { | 6988 | static 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; |
| 6936 | 6998 | ||
| 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; |
| 6963 | 7035 | ||
| 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; |
| 6978 | 7050 | ||
| 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 | } |
| 6982 | 7055 | ||
| ... | @@ -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 decreased | 9880 | // alignment can be decreased |
| 9794 | // bit offset attributes must match exactly | 9881 | // bit offset attributes must match exactly |
| 9795 | // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one | 9882 | // 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 | } |
| 9857 | 9970 | ||
| 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 const | 10001 | // 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 []T | 10758 | // *[N]T to []T |
| 10616 | // *[N]T to E![]T | 10759 | // *[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![]T | 10782 | // *[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 | } |
| 10669 | 10816 | ||
| 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 []T | 10861 | // [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); |
| 10716 | 10907 | ||
| 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 | } |
| 10958 | 11166 | ||
| 10959 | static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, | 11167 | static 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; |
| 10963 | 11171 | ||
| 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 | } |
| 10969 | 11177 | ||
| 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)); |
| 10971 | 11179 | ||
| 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; |
| 10981 | 11189 | ||
| 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 | } |
| 10998 | 11206 | ||
| 10999 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { | 11207 | static 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: // TODO | 12715 | case ConstCastResultIdFnArgNoAlias: // TODO |
| 12459 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO | 12716 | case ConstCastResultIdUnresolvedInferredErrSet: // TODO |
| 12460 | case ConstCastResultIdAsyncAllocatorType: // TODO | 12717 | 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 | } |
| 12586 | 12844 | ||
| 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. | ||
| 12849 | static 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 | |||
| 12883 | static 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 | |||
| 12587 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 12892 | static 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; |
| 12699 | 13004 | ||
| 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; |
| 12703 | 13008 | ||
| ... | @@ -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 | } |
| 12772 | 13077 | ||
| 12773 | |||
| 12774 | // cast from [N]T to []const T | 13078 | // cast from [N]T to []const T |
| 12775 | // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this | 13079 | // 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 | } |
| 12786 | 13090 | ||
| ... | @@ -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; |
| 12803 | 13107 | ||
| 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; |
| 12807 | 13111 | ||
| ... | @@ -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 | } |
| 12811 | 13115 | ||
| 12812 | // *[N]T to [*]T and [*c]T | 13116 | // *[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 | } |
| 12831 | 13162 | ||
| ... | @@ -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; |
| 12876 | 13207 | ||
| 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; |
| 12880 | 13211 | ||
| 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; |
| 12983 | 13314 | ||
| 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; |
| 12987 | 13318 | ||
| ... | @@ -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 | } |
| 12998 | 13329 | ||
| 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; |
| 13021 | 13352 | ||
| 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 | } |
| 13024 | 13355 | ||
| 13025 | // cast from enum literal to error union when payload is an enum | 13356 | // 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 | } |
| 13035 | 13366 | ||
| 13036 | // cast from union to the enum type of the union | 13367 | // 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_types | 13395 | (!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 | } |
| 13091 | 13404 | ||
| 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_void | 13427 | // cast from *T and [*]T to *c_void and ?*c_void |
| 13093 | // but don't do it if the actual type is a double pointer | 13428 | // 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 | } |
| 13132 | 13467 | ||
| 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 | } |
| 13190 | 13525 | ||
| 13191 | static IrInstruction *ir_implicit_cast_with_result(IrAnalyze *ira, IrInstruction *source_instr, | 13526 | static 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; |
| 13205 | 13540 | ||
| 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 | } |
| 13208 | 13543 | ||
| 13209 | static IrInstruction *ir_implicit_cast(IrAnalyze *ira, IrInstruction *value, ZigType *expected_type) { | 13544 | static 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 | } |
| 13212 | 13547 | ||
| 13213 | static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *ptr, | 13548 | static 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); |
| 13247 | 13585 | ||
| ... | @@ -14519,8 +14857,6 @@ static bool ok_float_op(IrBinOp op) { | ... | @@ -14519,8 +14857,6 @@ static bool ok_float_op(IrBinOp op) { |
| 14519 | } | 14857 | } |
| 14520 | 14858 | ||
| 14521 | static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { | 14859 | static 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 | } |
| 14540 | 14878 | ||
| 14541 | static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { | 14879 | static 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; |
| 14799 | 15137 | ||
| 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 | } |
| 14832 | 15185 | ||
| 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 | } |
| 14871 | 15241 | ||
| 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 blocks | 15255 | // 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); |
| 14880 | 15263 | ||
| 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); |
| 14889 | 15281 | ||
| 14890 | out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); | 15282 | out_val->data.x_struct.fields = alloc_const_vals_ptrs(2); |
| 14891 | 15283 | ||
| ... | @@ -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 byte | 15294 | result->value.type = get_pointer_to_type_extra2(ira->codegen, child_type, true, false, PtrLenUnknown, |
| 14903 | 15295 | 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); | ||
| 14906 | 15296 | ||
| 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 | } |
| 14915 | 15304 | ||
| 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 | } |
| 14921 | 15311 | ||
| 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 optimization | 15314 | // 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); |
| 14926 | 15317 | ||
| 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); |
| 14942 | 15342 | ||
| 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; |
| 14954 | 15354 | ||
| 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 | } | ||
| 14958 | 15378 | ||
| 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; |
| 14962 | 15382 | ||
| 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; |
| 14971 | 15385 | ||
| ... | @@ -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 | } |
| 14976 | 15390 | ||
| 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); | ||
| 14978 | 15394 | ||
| 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 | } | ||
| 14986 | 15401 | ||
| 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 | } |
| 14995 | 15410 | ||
| 14996 | // TODO optimize the buf case | 15411 | // 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); | ||
| 14999 | 15415 | ||
| 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); | 15438 | skip_computation: |
| 15012 | 15439 | 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 | } |
| 15015 | 15445 | ||
| 15016 | static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira, | 15446 | static 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); |
| 15915 | 16357 | ||
| ... | @@ -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); |
| 17284 | 17726 | ||
| 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); | ||
| 17286 | 17729 | ||
| 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); |
| 17294 | 17737 | ||
| 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 |
| 17882 | 18325 | ||
| 17883 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align) { | 18326 | static 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 | } |
| 17893 | 18339 | ||
| 17894 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align) { | 18340 | static 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 possible | 18516 | // figure out the largest alignment possible |
| 18065 | 18517 | ||
| ... | @@ -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; | ||
| 18172 | 18630 | ||
| 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; |
| 18182 | 18653 | ||
| 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; | ||
| 18191 | 18660 | ||
| 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 index | 18781 | // 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); |
| 18509 | 18984 | ||
| 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 | } |
| 19289 | 19764 | ||
| 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 above | 19869 | 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 | } |
| 19478 | 19975 | ||
| 19976 | static 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 | |||
| 19479 | static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr, | 19990 | static 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; |
| 19488 | 19996 | ||
| ... | @@ -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 |
| 19520 | 20028 | ||
| 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); | ||
| 19524 | 20033 | ||
| 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); |
| 19526 | 20035 | ||
| 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); |
| 20483 | 20992 | ||
| 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 |
| 20966 | 21475 | ||
| 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; |
| 20992 | 21501 | ||
| 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); |
| 21117 | 21626 | ||
| ... | @@ -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; |
| 21212 | 21721 | ||
| 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; |
| 21215 | 21724 | ||
| 21216 | // size: Size | 21725 | // 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 | } | ||
| 21249 | 21768 | ||
| 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; |
| 21262 | 21781 | ||
| 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); |
| 21265 | 21784 | ||
| 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); |
| 21355 | 21874 | ||
| 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; |
| 21358 | 21877 | ||
| 21359 | // len: usize | 21878 | // 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; |
| 21369 | 21888 | // sentinel: var | |
| 21889 | fields[2]->special = ConstValSpecialStatic; | ||
| 21890 | fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type); | ||
| 21891 | fields[2]->data.x_optional = type_entry->data.array.sentinel; | ||
| 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 |
| 21453 | 21975 | ||
| 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); |
| 21459 | 21981 | ||
| ... | @@ -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); |
| 21507 | 22029 | ||
| ... | @@ -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); |
| 21527 | 22049 | ||
| ... | @@ -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 |
| 21597 | 22119 | ||
| 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); |
| 21603 | 22125 | ||
| ... | @@ -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; |
| 21629 | 22151 | ||
| 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); |
| 21632 | 22154 | ||
| 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 |
| 21677 | 22199 | ||
| 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); |
| 21683 | 22205 | ||
| ... | @@ -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; |
| 21715 | 22237 | ||
| 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); |
| 21718 | 22240 | ||
| 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 |
| 21780 | 22302 | ||
| 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); |
| 21786 | 22308 | ||
| ... | @@ -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 | } |
| 21880 | 22402 | ||
| 22403 | static 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 | |||
| 21881 | static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index) | 22417 | static 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 | } |
| 21901 | 22437 | ||
| 21902 | static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) { | 22438 | static 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_host | 22495 | 0, // bit_offset_in_host |
| 21951 | 0, // host_int_bytes | 22496 | 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 | } |
| 22344 | 22897 | ||
| 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; |
| 25568 | 26121 | ||
| 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 | } |
| 26492 | 27051 | ||
| 26493 | static IrInstruction *ir_analyze_instruction_bit_cast_src(IrAnalyze *ira, IrInstructionBitCastSrc *instruction) { | 27052 | static 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; |
| 27514 | 28073 | ||
| 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; |
| 27575 | 28151 | ||
| 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) { |
| 848 | 848 | ||
| 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 | } |
| 1724 | 1728 | ||
| ... | @@ -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 | } |
| 1836 | 1840 | ||
| 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 | } |
| 1841 | 1847 | ||
| ... | @@ -1932,15 +1938,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) { | ... | @@ -1932,15 +1938,11 @@ static AstNode *ast_parse_asm_output(ParseContext *pc) { |
| 1932 | 1938 | ||
| 1933 | // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN | 1939 | // AsmOutputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN (MINUSRARROW TypeExpr / IDENTIFIER) RPAREN |
| 1934 | static AsmOutput *ast_parse_asm_output_item(ParseContext *pc) { | 1940 | static 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 | } | ||
| 1944 | 1946 | ||
| 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); |
| 1956 | 1958 | ||
| 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) { |
| 1978 | 1980 | ||
| 1979 | // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN | 1981 | // AsmInputItem <- LBRACKET IDENTIFIER RBRACKET STRINGLITERAL LPAREN Expr RPAREN |
| 1980 | static AsmInput *ast_parse_asm_input_item(ParseContext *pc) { | 1982 | static 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 | } | ||
| 1990 | 1988 | ||
| 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); |
| 1995 | 1993 | ||
| 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 | } |
| 2616 | 2614 | ||
| 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 { |
| 2626 | 2624 | 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 | } |
| 2647 | 2635 | ||
| 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 | } |
| 2692 | 2681 | ||
| 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 | } |
| 2697 | 2712 | ||
| 2698 | 2713 | ||
| ... | @@ -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; |
| 2767 | 2782 | ||
| 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 | } |
| 2774 | 2795 | ||
| ... | @@ -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 | // / PTRUNKNOWN | 2799 | // / PTRUNKNOWN |
| 2779 | // / PTRC | 2800 | // / PTRC |
| 2780 | static AstNode *ast_parse_ptr_type_start(ParseContext *pc) { | 2801 | static 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 | } |
| 2787 | 2815 | ||
| 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 | } |
| 2797 | 2830 | ||
| 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 | } | ||
| 2804 | 2848 | ||
| 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 | } |
| 2811 | 2860 | ||
| 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 | // none | 3148 | // 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_ZERO | 34 | case DIGIT_NON_ZERO |
| 35 | 35 | ||
| 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' |
| 89 | 89 | ||
| 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) { |
| 180 | enum TokenizeState { | 176 | enum 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 | }; |
| 235 | 226 | ||
| 236 | 227 | ||
| ... | @@ -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 | } |
| 285 | 275 | ||
| ... | @@ -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 { |
| 149 | 146 | ||
| 150 | struct TokenStrLit { | 147 | struct TokenStrLit { |
| 151 | Buf str; | 148 | Buf str; |
| 152 | bool is_c_str; | ||
| 153 | }; | 149 | }; |
| 154 | 150 | ||
| 155 | struct TokenCharLit { | 151 | struct 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 | } |
| 323 | 323 | ||
| 324 | static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) { | 324 | static 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 | |||
| 331 | static 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 | } |
| 337 | 329 | ||
| ... | @@ -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_node | 622 | // zig_type_node |
| 631 | 623 | ||
| 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) |
| 4936 | 4928 | ||
| 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 { |
| 87 | fn testZigInitLib(zig_exe: []const u8, dir_path: []const u8) !void { | 87 | fn 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 | } |
| 92 | 92 | ||
| 93 | fn testZigInitExe(zig_exe: []const u8, dir_path: []const u8) !void { | 93 | fn 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\n | 144 | \\ // 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"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub 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 | ); |
| 101 | 128 | ||
| 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 | ); |
| 808 | 848 | ||
| 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 | ); |
| 2461 | 2501 | ||
| 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 | ); |
| 2470 | 2511 | ||
| 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 | ); |
| 3380 | 3421 | ||
| 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 | ); |
| 3856 | 3897 | ||
| 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 | ); |
| 6235 | 6276 | ||
| 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 | ); |
| 6801 | 6842 | ||
| 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 | } |
| 133 | 133 | ||
| 134 | fn testSingleItemPtrArrayIndexSlice() void { | 134 | fn 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 | } |
| 139 | 146 | ||
| 140 | fn doSomeMangling(array: *[4]u8) void { | 147 | fn 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 | } |
| 295 | 302 | ||
| 296 | test "implicit cast zero sized array ptr to slice" { | 303 | test "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 | } |
| 301 | 315 | ||
| 302 | test "anonymous list literal syntax" { | 316 | test "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 | |||
| 351 | test "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 | } |
| 9 | 9 | ||
| 10 | fn testCastPtrOfArrayToSliceAndPtr() void { | 10 | fn 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 | } |
| 180 | 180 | ||
| 181 | test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" { | 181 | test "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 | } |
| 195 | fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { | 201 | fn 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 | } |
| 218 | 224 | ||
| 219 | fn testCastConstArrayRefToConstSlice() void { | 225 | fn 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 | } |
| 226 | 241 | ||
| 227 | test "peer type resolution: error and [N]T" { | 242 | test "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 | } |
| 311 | 326 | ||
| 312 | fn testCastPtrOfArrayToSliceAndPtr() void { | 327 | fn 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 | } |
| 321 | 347 | ||
| 322 | test "cast *[1][*]const u8 to [*]const ?[*]const u8" { | 348 | test "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 | } |
| 327 | 353 | ||
| 328 | test "@intCast comptime_int" { | 354 | test "@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 | } |
| 546 | 572 | ||
| 547 | test "peer cast *[0]T to E![]const T" { | 573 | test "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 | } |
| 554 | 580 | ||
| 555 | test "peer cast *[0]T to []const T" { | 581 | test "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 | |||
| 595 | test "*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 | |||
| 607 | test "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 | |||
| 625 | test "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; |
| 6 | 6 | ||
| 7 | test "const slice child" { | 7 | test "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 cast | 13 | argv = &strs; |
| 14 | argv = @ptrCast([*]const [*]const u8, &strs); | ||
| 15 | bar(strs.len); | 14 | bar(strs.len); |
| 16 | } | 15 | } |
| 17 | 16 |
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" { |
| 736 | 736 | ||
| 737 | test "slice bounds in comptime concatenation" { | 737 | test "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" { |
| 204 | 204 | ||
| 205 | test "multiline C string" { | 205 | test "multiline C string" { |
| 206 | const s1 = | 206 | const s1 = |
| 207 | c\\one | 207 | \\one |
| 208 | c\\two) | 208 | \\two) |
| 209 | c\\three | 209 | \\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 | } |
| 214 | 214 | ||
| ... | @@ -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 | } |
| 360 | 360 | ||
| 361 | test "C string concatenation" { | 361 | test "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); | ||
| 364 | 367 | ||
| 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 | } |
| 16 | 16 | ||
| 17 | test "pointer arithmetic" { | 17 | test "pointer arithmetic" { |
| 18 | var ptr = c"abcd"; | 18 | var ptr: [*]const u8 = "abcd"; |
| 19 | 19 | ||
| 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 | |||
| 204 | test "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 | |||
| 218 | test "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 | |||
| 230 | test "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 | |||
| 243 | test "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 | |||
| 254 | test "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 | } |
| 61 | 61 | ||
| 62 | test "implicit optional pointer to optional c_void pointer" { | 62 | test "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 | } |
| 37 | 37 | ||
| 38 | test "C pointer" { | 38 | test "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 | |||
| 69 | test "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 | |||
| 781 | test "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 | } |
| 12 | 12 | ||
| 13 | test "Type.MetaType" { | 13 | test "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 | } |
| 17 | 17 | ||
| 18 | test "Type.Void" { | 18 | test "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 | } |
| 22 | 22 | ||
| 23 | test "Type.Bool" { | 23 | test "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 | } |
| 27 | 27 | ||
| 28 | test "Type.NoReturn" { | 28 | test "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 | } |
| 32 | 32 | ||
| 33 | test "Type.Int" { | 33 | test "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 | } |
| 42 | 42 | ||
| 43 | test "Type.Float" { | 43 | test "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 | } |
| 50 | 50 | ||
| 51 | test "Type.Pointer" { | 51 | test "Type.Pointer" { |
| 52 | testTypes([_]type { | 52 | testTypes([_]type{ |
| 53 | // One Value Pointer Types | 53 | // 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 Types | 64 | // 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 Types | 75 | // 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 Types | 86 | // 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 | } |
| 95 | 95 | ||
| 96 | test "Type.Array" { | 96 | test "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 | } |
| 101 | 120 | ||
| 102 | test "Type.ComptimeFloat" { | 121 | test "Type.ComptimeFloat" { |
| 103 | testTypes([_]type {comptime_float}); | 122 | testTypes([_]type{comptime_float}); |
| 104 | } | 123 | } |
| 105 | test "Type.ComptimeInt" { | 124 | test "Type.ComptimeInt" { |
| 106 | testTypes([_]type {comptime_int}); | 125 | testTypes([_]type{comptime_int}); |
| 107 | } | 126 | } |
| 108 | test "Type.Undefined" { | 127 | test "Type.Undefined" { |
| 109 | testTypes([_]type {@typeOf(undefined)}); | 128 | testTypes([_]type{@typeOf(undefined)}); |
| 110 | } | 129 | } |
| 111 | test "Type.Null" { | 130 | test "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 | } |
| 50 | 51 | ||
| 51 | test "type info: unknown length pointer type info" { | 52 | test "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" { |
| 55 | 56 | ||
| 56 | fn testUnknownLenPtr() void { | 57 | fn 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 | } |
| 65 | 67 | ||
| 68 | test "type info: null terminated pointer type info" { | ||
| 69 | testNullTerminatedPtr(); | ||
| 70 | comptime testNullTerminatedPtr(); | ||
| 71 | } | ||
| 72 | |||
| 73 | fn 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 | |||
| 66 | test "type info: C pointer type info" { | 87 | test "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" { |
| 70 | 91 | ||
| 71 | fn testCPtr() void { | 92 | fn 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" { |
| 288 | fn testAnyFrame() void { | 309 | fn 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 | } |
| 294 | 315 | ||
| 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 { |
| 119 | extern fn c_array([10]u8) void; | 119 | extern fn c_array([10]u8) void; |
| 120 | 120 | ||
| 121 | test "C ABI array" { | 121 | test "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 | } |
| 125 | 125 |
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 | }); |
| 7 | 7 | ||
| 8 | const msg = c"Hello, world!\n"; | 8 | const msg = "Hello, world!\n"; |
| 9 | 9 | ||
| 10 | export fn main(argc: c_int, argv: **u8) c_int { | 10 | export 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 | ); |
| 221 | 221 | ||
| ... | @@ -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 | ); |
| 548 | 548 | ||
| 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 | ); |
| 1357 | 1357 | ||
| ... | @@ -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 | ); |
| 1528 | 1528 | ||
| 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 | ); |
| 1538 | 1538 | ||
| ... | @@ -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 | ); |