string literals are now null terminated

this also deletes C string literals from the language, and then makes
the std lib changes and compiler changes necessary to get the behavior
tests and std lib tests passing again.
master
Andrew Kelley 2019-11-19 20:29:08 -05:00
parent 21f344b3b9
commit 47f06be369
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
51 changed files with 986 additions and 716 deletions

View File

@ -328,7 +328,7 @@ pub const ChildProcess = struct {
const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
const dev_null_fd = if (any_ignore)
os.openC(c"/dev/null", os.O_RDWR, 0) catch |err| switch (err) {
os.openC("/dev/null", os.O_RDWR, 0) catch |err| switch (err) {
error.PathAlreadyExists => unreachable,
error.NoSpaceLeft => unreachable,
error.FileTooBig => unreachable,

View File

@ -610,8 +610,8 @@ test "x25519 rfc7748 vector2" {
}
test "x25519 rfc7748 one iteration" {
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";
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";
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".*;
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".*;
var k: [32]u8 = initial_value;
var u: [32]u8 = initial_value;
@ -634,8 +634,8 @@ test "x25519 rfc7748 1,000 iterations" {
return error.SkipZigTest;
}
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";
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";
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".*;
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".*;
var k: [32]u8 = initial_value;
var u: [32]u8 = initial_value;
@ -657,8 +657,8 @@ test "x25519 rfc7748 1,000,000 iterations" {
return error.SkipZigTest;
}
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";
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";
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".*;
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".*;
var k: [32]u8 = initial_value;
var u: [32]u8 = initial_value;

View File

@ -27,8 +27,8 @@ test "cstr fns" {
}
fn testCStrFnsImpl() void {
testing.expect(cmp(c"aoeu", c"aoez") == -1);
testing.expect(mem.len(u8, c"123456789") == 9);
testing.expect(cmp("aoeu", "aoez") == -1);
testing.expect(mem.len(u8, "123456789") == 9);
}
/// Returns a mutable slice with 1 more byte of length which is a null byte.

View File

@ -1,8 +1,6 @@
const std = @import("std.zig");
const math = std.math;
const debug = std.debug;
const assert = debug.assert;
const testing = std.testing;
const assert = std.debug.assert;
const mem = std.mem;
const builtin = @import("builtin");
const errol = @import("fmt/errol.zig");
@ -36,7 +34,7 @@ fn nextArg(comptime used_pos_args: *u32, comptime maybe_pos_arg: ?comptime_int,
fn peekIsAlign(comptime fmt: []const u8) bool {
// Should only be called during a state transition to the format segment.
std.debug.assert(fmt[0] == ':');
comptime assert(fmt[0] == ':');
inline for (([_]u8{ 1, 2 })[0..]) |i| {
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 {
}
test "parseInt" {
testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
std.testing.expect(if (parseInt(i32, " 10", 10)) |_| false else |err| err == error.InvalidCharacter);
std.testing.expect(if (parseInt(i32, "10 ", 10)) |_| false else |err| err == error.InvalidCharacter);
std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
std.testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255);
std.testing.expect(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
}
const ParseUnsignedError = error{
@ -1040,30 +1038,30 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
}
test "parseUnsigned" {
testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
std.testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16));
testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
std.testing.expect((try parseUnsigned(u32, "DeadBeef", 16)) == 0xDEADBEEF);
testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
std.testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8));
testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
std.testing.expect((try parseUnsigned(u32, "NUMBER", 36)) == 1442151747);
// these numbers should fit even though the radix itself doesn't fit in the destination type
testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
}
pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
@ -1134,19 +1132,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
const buf = buffer[0..];
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}), "-12345678"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}), "-bc614e"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}), "-BC614E"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 2, false, FormatOptions{}), "-101111000110000101001110"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 10, false, FormatOptions{}), "-12345678"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, false, FormatOptions{}), "-bc614e"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -12345678), 16, true, FormatOptions{}), "-BC614E"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}), "12345678"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 12345678), 10, true, FormatOptions{}), "12345678"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }), " 666"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 666), 10, false, FormatOptions{ .width = 6 }), " 666"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 6 }), " 1234"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(u32, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }), "+42"));
testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, 42), 10, false, FormatOptions{ .width = 3 }), "+42"));
std.testing.expect(mem.eql(u8, bufPrintIntToSlice(buf, @as(i32, -42), 10, false, FormatOptions{ .width = 3 }), "-42"));
}
fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) []u8 {
@ -1163,7 +1161,7 @@ test "parse u64 digit too big" {
test "parse unsigned comptime" {
comptime {
testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
}
}
@ -1218,23 +1216,23 @@ test "buffer" {
var context = BufPrintContext{ .remaining = buf1[0..] };
try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
var res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "1234"));
std.testing.expect(mem.eql(u8, res, "1234"));
context = BufPrintContext{ .remaining = buf1[0..] };
try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "a"));
std.testing.expect(mem.eql(u8, res, "a"));
context = BufPrintContext{ .remaining = buf1[0..] };
try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len];
testing.expect(mem.eql(u8, res, "1100"));
std.testing.expect(mem.eql(u8, res, "1100"));
}
}
test "array" {
{
const value: [3]u8 = "abc";
const value: [3]u8 = "abc".*;
try testFmt("array: abc\n", "array: {}\n", value);
try testFmt("array: abc\n", "array: {}\n", &value);
@ -1278,8 +1276,8 @@ test "pointer" {
}
test "cstr" {
try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C");
try testFmt("cstr: Test C \n", "cstr: {s:10}\n", c"Test C");
try testFmt("cstr: Test C\n", "cstr: {s}\n", "Test C");
try testFmt("cstr: Test C \n", "cstr: {s:10}\n", "Test C");
}
test "filesize" {
@ -1479,10 +1477,10 @@ test "union" {
var buf: [100]u8 = undefined;
const uu_result = try bufPrint(buf[0..], "{}", uu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
const eu_result = try bufPrint(buf[0..], "{}", eu_inst);
testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
}
test "enum" {
@ -1569,11 +1567,11 @@ pub fn trim(buf: []const u8) []const u8 {
}
test "trim" {
testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
testing.expect(mem.eql(u8, "", trim(" ")));
testing.expect(mem.eql(u8, "", trim("")));
testing.expect(mem.eql(u8, "abc", trim(" abc")));
testing.expect(mem.eql(u8, "abc", trim("abc ")));
std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
std.testing.expect(mem.eql(u8, "", trim(" ")));
std.testing.expect(mem.eql(u8, "", trim("")));
std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
}
pub fn isWhiteSpace(byte: u8) bool {
@ -1607,7 +1605,7 @@ test "formatIntValue with comptime_int" {
var buf = try std.Buffer.init(std.debug.global_allocator, "");
try formatIntValue(value, "", FormatOptions{}, &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append);
assert(mem.eql(u8, buf.toSlice(), "123456789123456789"));
std.testing.expect(mem.eql(u8, buf.toSlice(), "123456789123456789"));
}
test "formatType max_depth" {
@ -1661,19 +1659,19 @@ test "formatType max_depth" {
var buf0 = try std.Buffer.init(std.debug.global_allocator, "");
try formatType(inst, "", FormatOptions{}, &buf0, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 0);
assert(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
var buf1 = try std.Buffer.init(std.debug.global_allocator, "");
try formatType(inst, "", FormatOptions{}, &buf1, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 1);
assert(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
var buf2 = try std.Buffer.init(std.debug.global_allocator, "");
try formatType(inst, "", FormatOptions{}, &buf2, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 2);
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) }"));
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) }"));
var buf3 = try std.Buffer.init(std.debug.global_allocator, "");
try formatType(inst, "", FormatOptions{}, &buf3, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append, 3);
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) }"));
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) }"));
}
test "positional" {

View File

@ -1240,7 +1240,7 @@ pub const OpenSelfExeError = os.OpenError || os.windows.CreateFileError || SelfE
pub fn openSelfExe() OpenSelfExeError!File {
if (builtin.os == .linux) {
return File.openReadC(c"/proc/self/exe");
return File.openReadC("/proc/self/exe");
}
if (builtin.os == .windows) {
const wide_slice = selfExePathW();
@ -1280,7 +1280,7 @@ pub fn selfExePath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]u8 {
return mem.toSlice(u8, out_buffer);
}
switch (builtin.os) {
.linux => return os.readlinkC(c"/proc/self/exe", out_buffer),
.linux => return os.readlinkC("/proc/self/exe", out_buffer),
.freebsd, .dragonfly => {
var mib = [4]c_int{ os.CTL_KERN, os.KERN_PROC, os.KERN_PROC_PATHNAME, -1 };
var out_len: usize = out_buffer.len;
@ -1326,7 +1326,7 @@ pub fn selfExeDirPath(out_buffer: *[MAX_PATH_BYTES]u8) SelfExePathError![]const
// the file path looks something like `/a/b/c/exe (deleted)`
// This path cannot be opened, but it's valid for determining the directory
// the executable was in when it was run.
const full_exe_path = try os.readlinkC(c"/proc/self/exe", out_buffer);
const full_exe_path = try os.readlinkC("/proc/self/exe", out_buffer);
// Assume that /proc/self/exe has an absolute path, and therefore dirname
// will not return null.
return path.dirname(full_exe_path).?;

View File

@ -172,7 +172,7 @@ pub const File = struct {
if (self.isTty()) {
if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) {
// Use getenvC to workaround https://github.com/ziglang/zig/issues/3511
if (os.getenvC(c"TERM")) |term| {
if (os.getenvC("TERM")) |term| {
if (std.mem.eql(u8, term, "dumb"))
return false;
}

View File

@ -394,7 +394,7 @@ pub fn resolveWindows(allocator: *Allocator, paths: []const []const u8) ![]u8 {
}
// determine which disk designator we will result with, if any
var result_drive_buf = "_:";
var result_drive_buf = "_:".*;
var result_disk_designator: []const u8 = "";
var have_drive_kind = WindowsPath.Kind.None;
var have_abs_path = false;

View File

@ -202,70 +202,70 @@ const test_key = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x
test "siphash64-2-4 sanity" {
const vectors = [_][8]u8{
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // ""
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00"
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc
"\x2d\x7e\xfb\xd7\x96\x66\x67\x85",
"\xb7\x87\x71\x27\xe0\x94\x27\xcf",
"\x8d\xa6\x99\xcd\x64\x55\x76\x18",
"\xce\xe3\xfe\x58\x6e\x46\xc9\xcb",
"\x37\xd1\x01\x8b\xf5\x00\x02\xab",
"\x62\x24\x93\x9a\x79\xf5\xf5\x93",
"\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e",
"\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a",
"\xa7\xad\x6b\x22\x46\x2f\xb3\xf4",
"\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75",
"\x90\x3d\x84\xc0\x27\x56\xea\x14",
"\xee\xf2\x7a\x8e\x90\xca\x23\xf7",
"\xe5\x45\xbe\x49\x61\xca\x29\xa1",
"\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f",
"\x94\x47\xbe\x2c\xf5\xe9\x9a\x69",
"\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b",
"\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb",
"\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe",
"\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0",
"\x88\x3e\xa3\xe3\x95\x67\x53\x93",
"\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8",
"\x94\xaf\x49\xf6\xc6\x50\xad\xb8",
"\xea\xb8\x85\x8a\xde\x92\xe1\xbc",
"\xf3\x15\xbb\x5b\xb8\x35\xd8\x17",
"\xad\xcf\x6b\x07\x63\x61\x2e\x2f",
"\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde",
"\x71\x65\x95\x87\x66\x50\xa2\xa6",
"\x28\xef\x49\x5c\x53\xa3\x87\xad",
"\x42\xc3\x41\xd8\xfa\x92\xd8\x32",
"\xce\x7c\xf2\x72\x2f\x51\x27\x71",
"\xe3\x78\x59\xf9\x46\x23\xf3\xa7",
"\x38\x12\x05\xbb\x1a\xb0\xe0\x12",
"\xae\x97\xa1\x0f\xd4\x34\xe0\x15",
"\xb4\xa3\x15\x08\xbe\xff\x4d\x31",
"\x81\x39\x62\x29\xf0\x90\x79\x02",
"\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca",
"\x5c\x73\x33\x6a\x76\xd8\xbf\x9a",
"\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e",
"\x92\x59\x58\xfc\xd6\x42\x0c\xad",
"\xa9\x15\xc2\x9b\xc8\x06\x73\x18",
"\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4",
"\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9",
"\x87\x57\x75\x19\x04\x8f\x53\xa9",
"\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb",
"\xeb\x75\x09\x5c\xcd\x98\x6c\xd0",
"\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6",
"\x96\xaf\xad\xfc\x2c\xe6\x66\xc7",
"\x72\xfe\x52\x97\x5a\x43\x64\xee",
"\x5a\x16\x45\xb2\x76\xd5\x92\xa1",
"\xb2\x74\xcb\x8e\xbf\x87\x87\x0a",
"\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81",
"\xea\xec\xb2\xa3\x0b\x22\xa8\x7f",
"\x99\x24\xa4\x3c\xc1\x31\x57\x24",
"\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7",
"\x0b\x1a\x2a\x32\x65\xd5\x1a\xea",
"\x13\x50\x79\xa3\x23\x1c\xe6\x60",
"\x93\x2b\x28\x46\xe4\xd7\x06\x66",
"\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c",
"\xf3\x25\x96\x5c\xa1\x6d\x62\x9f",
"\x57\x5f\xf2\x8e\x60\x38\x1b\xe5",
"\x72\x45\x06\xeb\x4c\x32\x8a\x95",
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72".*, // ""
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74".*, // "\x00"
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d".*, // "\x00\x01" ... etc
"\x2d\x7e\xfb\xd7\x96\x66\x67\x85".*,
"\xb7\x87\x71\x27\xe0\x94\x27\xcf".*,
"\x8d\xa6\x99\xcd\x64\x55\x76\x18".*,
"\xce\xe3\xfe\x58\x6e\x46\xc9\xcb".*,
"\x37\xd1\x01\x8b\xf5\x00\x02\xab".*,
"\x62\x24\x93\x9a\x79\xf5\xf5\x93".*,
"\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e".*,
"\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a".*,
"\xa7\xad\x6b\x22\x46\x2f\xb3\xf4".*,
"\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75".*,
"\x90\x3d\x84\xc0\x27\x56\xea\x14".*,
"\xee\xf2\x7a\x8e\x90\xca\x23\xf7".*,
"\xe5\x45\xbe\x49\x61\xca\x29\xa1".*,
"\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f".*,
"\x94\x47\xbe\x2c\xf5\xe9\x9a\x69".*,
"\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b".*,
"\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb".*,
"\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe".*,
"\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0".*,
"\x88\x3e\xa3\xe3\x95\x67\x53\x93".*,
"\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8".*,
"\x94\xaf\x49\xf6\xc6\x50\xad\xb8".*,
"\xea\xb8\x85\x8a\xde\x92\xe1\xbc".*,
"\xf3\x15\xbb\x5b\xb8\x35\xd8\x17".*,
"\xad\xcf\x6b\x07\x63\x61\x2e\x2f".*,
"\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde".*,
"\x71\x65\x95\x87\x66\x50\xa2\xa6".*,
"\x28\xef\x49\x5c\x53\xa3\x87\xad".*,
"\x42\xc3\x41\xd8\xfa\x92\xd8\x32".*,
"\xce\x7c\xf2\x72\x2f\x51\x27\x71".*,
"\xe3\x78\x59\xf9\x46\x23\xf3\xa7".*,
"\x38\x12\x05\xbb\x1a\xb0\xe0\x12".*,
"\xae\x97\xa1\x0f\xd4\x34\xe0\x15".*,
"\xb4\xa3\x15\x08\xbe\xff\x4d\x31".*,
"\x81\x39\x62\x29\xf0\x90\x79\x02".*,
"\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca".*,
"\x5c\x73\x33\x6a\x76\xd8\xbf\x9a".*,
"\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e".*,
"\x92\x59\x58\xfc\xd6\x42\x0c\xad".*,
"\xa9\x15\xc2\x9b\xc8\x06\x73\x18".*,
"\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4".*,
"\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9".*,
"\x87\x57\x75\x19\x04\x8f\x53\xa9".*,
"\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb".*,
"\xeb\x75\x09\x5c\xcd\x98\x6c\xd0".*,
"\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6".*,
"\x96\xaf\xad\xfc\x2c\xe6\x66\xc7".*,
"\x72\xfe\x52\x97\x5a\x43\x64\xee".*,
"\x5a\x16\x45\xb2\x76\xd5\x92\xa1".*,
"\xb2\x74\xcb\x8e\xbf\x87\x87\x0a".*,
"\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81".*,
"\xea\xec\xb2\xa3\x0b\x22\xa8\x7f".*,
"\x99\x24\xa4\x3c\xc1\x31\x57\x24".*,
"\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7".*,
"\x0b\x1a\x2a\x32\x65\xd5\x1a\xea".*,
"\x13\x50\x79\xa3\x23\x1c\xe6\x60".*,
"\x93\x2b\x28\x46\xe4\xd7\x06\x66".*,
"\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c".*,
"\xf3\x25\x96\x5c\xa1\x6d\x62\x9f".*,
"\x57\x5f\xf2\x8e\x60\x38\x1b\xe5".*,
"\x72\x45\x06\xeb\x4c\x32\x8a\x95".*,
};
const siphash = SipHash64(2, 4);
@ -281,70 +281,70 @@ test "siphash64-2-4 sanity" {
test "siphash128-2-4 sanity" {
const vectors = [_][16]u8{
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93",
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45",
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4",
"\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51",
"\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79",
"\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27",
"\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e",
"\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39",
"\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4",
"\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed",
"\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba",
"\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18",
"\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25",
"\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7",
"\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02",
"\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9",
"\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77",
"\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40",
"\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23",
"\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1",
"\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb",
"\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12",
"\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae",
"\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c",
"\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad",
"\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f",
"\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66",
"\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94",
"\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4",
"\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7",
"\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87",
"\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35",
"\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68",
"\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf",
"\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde",
"\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8",
"\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11",
"\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b",
"\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5",
"\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9",
"\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8",
"\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb",
"\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b",
"\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89",
"\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42",
"\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c",
"\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02",
"\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b",
"\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16",
"\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03",
"\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f",
"\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38",
"\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c",
"\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e",
"\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87",
"\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda",
"\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36",
"\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e",
"\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d",
"\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59",
"\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40",
"\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a",
"\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd",
"\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c",
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93".*,
"\xda\x87\xc1\xd8\x6b\x99\xaf\x44\x34\x76\x59\x11\x9b\x22\xfc\x45".*,
"\x81\x77\x22\x8d\xa4\xa4\x5d\xc7\xfc\xa3\x8b\xde\xf6\x0a\xff\xe4".*,
"\x9c\x70\xb6\x0c\x52\x67\xa9\x4e\x5f\x33\xb6\xb0\x29\x85\xed\x51".*,
"\xf8\x81\x64\xc1\x2d\x9c\x8f\xaf\x7d\x0f\x6e\x7c\x7b\xcd\x55\x79".*,
"\x13\x68\x87\x59\x80\x77\x6f\x88\x54\x52\x7a\x07\x69\x0e\x96\x27".*,
"\x14\xee\xca\x33\x8b\x20\x86\x13\x48\x5e\xa0\x30\x8f\xd7\xa1\x5e".*,
"\xa1\xf1\xeb\xbe\xd8\xdb\xc1\x53\xc0\xb8\x4a\xa6\x1f\xf0\x82\x39".*,
"\x3b\x62\xa9\xba\x62\x58\xf5\x61\x0f\x83\xe2\x64\xf3\x14\x97\xb4".*,
"\x26\x44\x99\x06\x0a\xd9\xba\xab\xc4\x7f\x8b\x02\xbb\x6d\x71\xed".*,
"\x00\x11\x0d\xc3\x78\x14\x69\x56\xc9\x54\x47\xd3\xf3\xd0\xfb\xba".*,
"\x01\x51\xc5\x68\x38\x6b\x66\x77\xa2\xb4\xdc\x6f\x81\xe5\xdc\x18".*,
"\xd6\x26\xb2\x66\x90\x5e\xf3\x58\x82\x63\x4d\xf6\x85\x32\xc1\x25".*,
"\x98\x69\xe2\x47\xe9\xc0\x8b\x10\xd0\x29\x93\x4f\xc4\xb9\x52\xf7".*,
"\x31\xfc\xef\xac\x66\xd7\xde\x9c\x7e\xc7\x48\x5f\xe4\x49\x49\x02".*,
"\x54\x93\xe9\x99\x33\xb0\xa8\x11\x7e\x08\xec\x0f\x97\xcf\xc3\xd9".*,
"\x6e\xe2\xa4\xca\x67\xb0\x54\xbb\xfd\x33\x15\xbf\x85\x23\x05\x77".*,
"\x47\x3d\x06\xe8\x73\x8d\xb8\x98\x54\xc0\x66\xc4\x7a\xe4\x77\x40".*,
"\xa4\x26\xe5\xe4\x23\xbf\x48\x85\x29\x4d\xa4\x81\xfe\xae\xf7\x23".*,
"\x78\x01\x77\x31\xcf\x65\xfa\xb0\x74\xd5\x20\x89\x52\x51\x2e\xb1".*,
"\x9e\x25\xfc\x83\x3f\x22\x90\x73\x3e\x93\x44\xa5\xe8\x38\x39\xeb".*,
"\x56\x8e\x49\x5a\xbe\x52\x5a\x21\x8a\x22\x14\xcd\x3e\x07\x1d\x12".*,
"\x4a\x29\xb5\x45\x52\xd1\x6b\x9a\x46\x9c\x10\x52\x8e\xff\x0a\xae".*,
"\xc9\xd1\x84\xdd\xd5\xa9\xf5\xe0\xcf\x8c\xe2\x9a\x9a\xbf\x69\x1c".*,
"\x2d\xb4\x79\xae\x78\xbd\x50\xd8\x88\x2a\x8a\x17\x8a\x61\x32\xad".*,
"\x8e\xce\x5f\x04\x2d\x5e\x44\x7b\x50\x51\xb9\xea\xcb\x8d\x8f\x6f".*,
"\x9c\x0b\x53\xb4\xb3\xc3\x07\xe8\x7e\xae\xe0\x86\x78\x14\x1f\x66".*,
"\xab\xf2\x48\xaf\x69\xa6\xea\xe4\xbf\xd3\xeb\x2f\x12\x9e\xeb\x94".*,
"\x06\x64\xda\x16\x68\x57\x4b\x88\xb9\x35\xf3\x02\x73\x58\xae\xf4".*,
"\xaa\x4b\x9d\xc4\xbf\x33\x7d\xe9\x0c\xd4\xfd\x3c\x46\x7c\x6a\xb7".*,
"\xea\x5c\x7f\x47\x1f\xaf\x6b\xde\x2b\x1a\xd7\xd4\x68\x6d\x22\x87".*,
"\x29\x39\xb0\x18\x32\x23\xfa\xfc\x17\x23\xde\x4f\x52\xc4\x3d\x35".*,
"\x7c\x39\x56\xca\x5e\xea\xfc\x3e\x36\x3e\x9d\x55\x65\x46\xeb\x68".*,
"\x77\xc6\x07\x71\x46\xf0\x1c\x32\xb6\xb6\x9d\x5f\x4e\xa9\xff\xcf".*,
"\x37\xa6\x98\x6c\xb8\x84\x7e\xdf\x09\x25\xf0\xf1\x30\x9b\x54\xde".*,
"\xa7\x05\xf0\xe6\x9d\xa9\xa8\xf9\x07\x24\x1a\x2e\x92\x3c\x8c\xc8".*,
"\x3d\xc4\x7d\x1f\x29\xc4\x48\x46\x1e\x9e\x76\xed\x90\x4f\x67\x11".*,
"\x0d\x62\xbf\x01\xe6\xfc\x0e\x1a\x0d\x3c\x47\x51\xc5\xd3\x69\x2b".*,
"\x8c\x03\x46\x8b\xca\x7c\x66\x9e\xe4\xfd\x5e\x08\x4b\xbe\xe7\xb5".*,
"\x52\x8a\x5b\xb9\x3b\xaf\x2c\x9c\x44\x73\xcc\xe5\xd0\xd2\x2b\xd9".*,
"\xdf\x6a\x30\x1e\x95\xc9\x5d\xad\x97\xae\x0c\xc8\xc6\x91\x3b\xd8".*,
"\x80\x11\x89\x90\x2c\x85\x7f\x39\xe7\x35\x91\x28\x5e\x70\xb6\xdb".*,
"\xe6\x17\x34\x6a\xc9\xc2\x31\xbb\x36\x50\xae\x34\xcc\xca\x0c\x5b".*,
"\x27\xd9\x34\x37\xef\xb7\x21\xaa\x40\x18\x21\xdc\xec\x5a\xdf\x89".*,
"\x89\x23\x7d\x9d\xed\x9c\x5e\x78\xd8\xb1\xc9\xb1\x66\xcc\x73\x42".*,
"\x4a\x6d\x80\x91\xbf\x5e\x7d\x65\x11\x89\xfa\x94\xa2\x50\xb1\x4c".*,
"\x0e\x33\xf9\x60\x55\xe7\xae\x89\x3f\xfc\x0e\x3d\xcf\x49\x29\x02".*,
"\xe6\x1c\x43\x2b\x72\x0b\x19\xd1\x8e\xc8\xd8\x4b\xdc\x63\x15\x1b".*,
"\xf7\xe5\xae\xf5\x49\xf7\x82\xcf\x37\x90\x55\xa6\x08\x26\x9b\x16".*,
"\x43\x8d\x03\x0f\xd0\xb7\xa5\x4f\xa8\x37\xf2\xad\x20\x1a\x64\x03".*,
"\xa5\x90\xd3\xee\x4f\xbf\x04\xe3\x24\x7e\x0d\x27\xf2\x86\x42\x3f".*,
"\x5f\xe2\xc1\xa1\x72\xfe\x93\xc4\xb1\x5c\xd3\x7c\xae\xf9\xf5\x38".*,
"\x2c\x97\x32\x5c\xbd\x06\xb3\x6e\xb2\x13\x3d\xd0\x8b\x3a\x01\x7c".*,
"\x92\xc8\x14\x22\x7a\x6b\xca\x94\x9f\xf0\x65\x9f\x00\x2a\xd3\x9e".*,
"\xdc\xe8\x50\x11\x0b\xd8\x32\x8c\xfb\xd5\x08\x41\xd6\x91\x1d\x87".*,
"\x67\xf1\x49\x84\xc7\xda\x79\x12\x48\xe3\x2b\xb5\x92\x25\x83\xda".*,
"\x19\x38\xf2\xcf\x72\xd5\x4e\xe9\x7e\x94\x16\x6f\xa9\x1d\x2a\x36".*,
"\x74\x48\x1e\x96\x46\xed\x49\xfe\x0f\x62\x24\x30\x16\x04\x69\x8e".*,
"\x57\xfc\xa5\xde\x98\xa9\xd6\xd8\x00\x64\x38\xd0\x58\x3d\x8a\x1d".*,
"\x9f\xec\xde\x1c\xef\xdc\x1c\xbe\xd4\x76\x36\x74\xd9\x57\x53\x59".*,
"\xe3\x04\x0c\x00\xeb\x28\xf1\x53\x66\xca\x73\xcb\xd8\x72\xe7\x40".*,
"\x76\x97\x00\x9a\x6a\x83\x1d\xfe\xcc\xa9\x1c\x59\x93\x67\x0f\x7a".*,
"\x58\x53\x54\x23\x21\xf5\x67\xa0\x05\xd5\x47\xa4\xf0\x47\x59\xbd".*,
"\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c".*,
};
const siphash = SipHash128(2, 4);

View File

@ -595,8 +595,8 @@ test "Deserializer bad data" {
test "c out stream" {
if (!builtin.link_libc) return error.SkipZigTest;
const filename = c"tmp_io_test_file.txt";
const out_file = std.c.fopen(filename, c"w") orelse return error.UnableToOpenTestFile;
const filename = "tmp_io_test_file.txt";
const out_file = std.c.fopen(filename, "w") orelse return error.UnableToOpenTestFile;
defer {
_ = std.c.fclose(out_file);
fs.deleteFileC(filename) catch {};

View File

@ -1408,7 +1408,9 @@ test "toBytes" {
fn BytesAsValueReturnType(comptime T: type, comptime B: type) type {
const size = @as(usize, @sizeOf(T));
if (comptime !trait.is(builtin.TypeId.Pointer)(B) or meta.Child(B) != [size]u8) {
if (comptime !trait.is(builtin.TypeId.Pointer)(B) or
(meta.Child(B) != [size]u8 and meta.Child(B) != [size]null u8))
{
@compileError("expected *[N]u8 " ++ ", passed " ++ @typeName(B));
}
@ -1430,12 +1432,12 @@ test "bytesAsValue" {
builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
};
testing.expect(deadbeef == bytesAsValue(u32, &deadbeef_bytes).*);
testing.expect(deadbeef == bytesAsValue(u32, deadbeef_bytes).*);
var codeface_bytes = switch (builtin.endian) {
var codeface_bytes: [4]u8 = switch (builtin.endian) {
builtin.Endian.Big => "\xC0\xDE\xFA\xCE",
builtin.Endian.Little => "\xCE\xFA\xDE\xC0",
};
}.*;
var codeface = bytesAsValue(u32, &codeface_bytes);
testing.expect(codeface.* == 0xC0DEFACE);
codeface.* = 0;
@ -1456,14 +1458,14 @@ test "bytesAsValue" {
.d = 0xA1,
};
const inst_bytes = "\xBE\xEF\xDE\xA1";
const inst2 = bytesAsValue(S, &inst_bytes);
const inst2 = bytesAsValue(S, inst_bytes);
testing.expect(meta.eql(inst, inst2.*));
}
///Given a pointer to an array of bytes, returns a value of the specified type backed by a
/// copy of those bytes.
pub fn bytesToValue(comptime T: type, bytes: var) T {
return bytesAsValue(T, &bytes).*;
return bytesAsValue(T, bytes).*;
}
test "bytesToValue" {
const deadbeef_bytes = switch (builtin.endian) {
@ -1491,11 +1493,11 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
}
test "subArrayPtr" {
const a1 = "abcdef";
const a1: [6]u8 = "abcdef".*;
const sub1 = subArrayPtr(&a1, 2, 3);
testing.expect(eql(u8, sub1.*, "cde"));
var a2 = "abcdef";
var a2: [6]u8 = "abcdef".*;
var sub2 = subArrayPtr(&a2, 2, 3);
testing.expect(eql(u8, sub2, "cde"));

View File

@ -469,19 +469,19 @@ test "std.meta.eql" {
const s_1 = S{
.a = 134,
.b = 123.3,
.c = "12345",
.c = "12345".*,
};
const s_2 = S{
.a = 1,
.b = 123.3,
.c = "54321",
.c = "54321".*,
};
const s_3 = S{
.a = 134,
.b = 123.3,
.c = "12345",
.c = "12345".*,
};
const u_1 = U{ .f = 24 };
@ -494,9 +494,9 @@ test "std.meta.eql" {
testing.expect(eql(u_1, u_3));
testing.expect(!eql(u_1, u_2));
var a1 = "abcdef";
var a2 = "abcdef";
var a3 = "ghijkl";
var a1 = "abcdef".*;
var a2 = "abcdef".*;
var a3 = "ghijkl".*;
testing.expect(eql(a1, a2));
testing.expect(!eql(a1, a3));
@ -558,4 +558,3 @@ pub fn refAllDecls(comptime T: type) void {
if (!builtin.is_test) return;
_ = declarations(T);
}

View File

@ -319,7 +319,6 @@ test "std.meta.trait.isNumber" {
testing.expect(!isNumber(NotANumber));
}
///
pub fn isConstPtr(comptime T: type) bool {
if (!comptime is(builtin.TypeId.Pointer)(T)) return false;
const info = @typeInfo(T);
@ -335,7 +334,6 @@ test "std.meta.trait.isConstPtr" {
testing.expect(!isConstPtr(@typeOf(6)));
}
///
pub fn isContainer(comptime T: type) bool {
const info = @typeInfo(T);
return switch (info) {

View File

@ -666,35 +666,35 @@ const Policy = struct {
const defined_policies = [_]Policy{
Policy{
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01",
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01".*,
.len = 15,
.mask = 0xff,
.prec = 50,
.label = 0,
},
Policy{
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00",
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00".*,
.len = 11,
.mask = 0xff,
.prec = 35,
.label = 4,
},
Policy{
.addr = "\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
.addr = "\x20\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
.len = 1,
.mask = 0xff,
.prec = 30,
.label = 2,
},
Policy{
.addr = "\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
.addr = "\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
.len = 3,
.mask = 0xff,
.prec = 5,
.label = 5,
},
Policy{
.addr = "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
.addr = "\xfc\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
.len = 0,
.mask = 0xfe,
.prec = 3,
@ -708,7 +708,7 @@ const defined_policies = [_]Policy{
// { "\x3f\xfe", 1, 0xff, 1, 12 },
// Last rule must match all addresses to stop loop.
Policy{
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
.addr = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00".*,
.len = 0,
.mask = 0,
.prec = 40,
@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(
family: os.sa_family_t,
port: u16,
) !void {
const file = fs.File.openReadC(c"/etc/hosts") catch |err| switch (err) {
const file = fs.File.openReadC("/etc/hosts") catch |err| switch (err) {
error.FileNotFound,
error.NotDir,
error.AccessDenied,
@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
};
errdefer rc.deinit();
const file = fs.File.openReadC(c"/etc/resolv.conf") catch |err| switch (err) {
const file = fs.File.openReadC("/etc/resolv.conf") catch |err| switch (err) {
error.FileNotFound,
error.NotDir,
error.AccessDenied,

View File

@ -157,7 +157,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
}
fn getRandomBytesDevURandom(buf: []u8) !void {
const fd = try openC(c"/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
const fd = try openC("/dev/urandom", O_RDONLY | O_CLOEXEC, 0);
defer close(fd);
const st = try fstat(fd);
@ -2674,7 +2674,7 @@ pub fn dl_iterate_phdr(
if (it.end()) {
var info = dl_phdr_info{
.dlpi_addr = elf_base,
.dlpi_name = c"/proc/self/exe",
.dlpi_name = "/proc/self/exe",
.dlpi_phdr = phdrs.ptr,
.dlpi_phnum = ehdr.e_phnum,
};

View File

@ -1053,7 +1053,7 @@ pub fn dl_iterate_phdr(comptime T: type, callback: extern fn (info: *dl_phdr_inf
if (it.end()) {
var info = dl_phdr_info{
.dlpi_addr = elf_base,
.dlpi_name = c"/proc/self/exe",
.dlpi_name = "/proc/self/exe",
.dlpi_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
.dlpi_phnum = __ehdr_start.e_phnum,
};

View File

@ -56,7 +56,7 @@ test "statx" {
}
var statx_buf: linux.Statx = undefined;
switch (linux.getErrno(linux.statx(file.handle, c"", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
switch (linux.getErrno(linux.statx(file.handle, "", linux.AT_EMPTY_PATH, linux.STATX_BASIC_STATS, &statx_buf))) {
0 => {},
// The statx syscall was only introduced in linux 4.11
linux.ENOSYS => return error.SkipZigTest,
@ -64,7 +64,7 @@ test "statx" {
}
var stat_buf: linux.Stat = undefined;
switch (linux.getErrno(linux.fstatat(file.handle, c"", &stat_buf, linux.AT_EMPTY_PATH))) {
switch (linux.getErrno(linux.fstatat(file.handle, "", &stat_buf, linux.AT_EMPTY_PATH))) {
0 => {},
else => unreachable,
}

View File

@ -473,14 +473,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
}
test "windows arg parsing" {
testWindowsCmdLine(c"a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
testWindowsCmdLine(c"\"abc\" d e", [_][]const u8{ "abc", "d", "e" });
testWindowsCmdLine(c"a\\\\\\b d\"e f\"g h", [_][]const u8{ "a\\\\\\b", "de fg", "h" });
testWindowsCmdLine(c"a\\\\\\\"b c d", [_][]const u8{ "a\\\"b", "c", "d" });
testWindowsCmdLine(c"a\\\\\\\\\"b c\" d e", [_][]const u8{ "a\\\\b c", "d", "e" });
testWindowsCmdLine(c"a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
testWindowsCmdLine("a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
testWindowsCmdLine("\"abc\" d e", [_][]const u8{ "abc", "d", "e" });
testWindowsCmdLine("a\\\\\\b d\"e f\"g h", [_][]const u8{ "a\\\\\\b", "de fg", "h" });
testWindowsCmdLine("a\\\\\\\"b c d", [_][]const u8{ "a\\\"b", "c", "d" });
testWindowsCmdLine("a\\\\\\\\\"b c\" d e", [_][]const u8{ "a\\\\b c", "d", "e" });
testWindowsCmdLine("a b\tc \"d f", [_][]const u8{ "a", "b", "c", "\"d", "f" });
testWindowsCmdLine(c"\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
testWindowsCmdLine("\".\\..\\zig-cache\\build\" \"bin\\zig.exe\" \".\\..\" \".\\..\\zig-cache\" \"--help\"", [_][]const u8{
".\\..\\zig-cache\\build",
"bin\\zig.exe",
".\\..",

View File

@ -66,14 +66,14 @@ extern fn strncmp(_l: [*]const u8, _r: [*]const u8, _n: usize) c_int {
}
extern fn strerror(errnum: c_int) [*]const u8 {
return c"TODO strerror implementation";
return "TODO strerror implementation";
}
test "strncmp" {
std.testing.expect(strncmp(c"a", c"b", 1) == -1);
std.testing.expect(strncmp(c"a", c"c", 1) == -2);
std.testing.expect(strncmp(c"b", c"a", 1) == 1);
std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253);
std.testing.expect(strncmp("a", "b", 1) == -1);
std.testing.expect(strncmp("a", "c", 1) == -2);
std.testing.expect(strncmp("b", "a", 1) == 1);
std.testing.expect(strncmp("\xff", "\x02", 1) == 253);
}
// Avoid dragging in the runtime safety mechanisms into this .o file,

View File

@ -353,7 +353,7 @@ pub const Thread = struct {
}
var count: c_int = undefined;
var count_len: usize = @sizeOf(c_int);
const name = if (comptime std.Target.current.isDarwin()) c"hw.logicalcpu" else c"hw.ncpu";
const name = if (comptime std.Target.current.isDarwin()) "hw.logicalcpu" else "hw.ncpu";
os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {
error.NameTooLong => unreachable,
else => |e| return e,

View File

@ -3,7 +3,7 @@ const testing = std.testing;
const valgrind = std.valgrind;
pub const MemCheckClientRequest = extern enum {
MakeMemNoAccess = valgrind.ToolBase("MC"),
MakeMemNoAccess = valgrind.ToolBase("MC".*),
MakeMemUndefined,
MakeMemDefined,
Discard,

View File

@ -52,7 +52,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
u32(c.ZIG_VERSION_MINOR),
u32(c.ZIG_VERSION_PATCH),
);
const flags = c"";
const flags = "";
const runtime_version = 0;
const compile_unit_file = llvm.CreateFile(
dibuilder,
@ -68,7 +68,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
is_optimized,
flags,
runtime_version,
c"",
"",
0,
!comp.strip,
) orelse return error.OutOfMemory;
@ -402,7 +402,7 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Poin
if (child_type.handleIsPtr()) {
return ptr;
}
return try renderLoad(ofile, ptr, ptr_type, c"");
return try renderLoad(ofile, ptr, ptr_type, "");
}
pub fn renderStoreUntyped(

View File

@ -511,8 +511,8 @@ pub const Compilation = struct {
comp.target_machine = llvm.CreateTargetMachine(
comp.llvm_target,
comp.llvm_triple.ptr(),
target_specific_cpu_args orelse c"",
target_specific_cpu_features orelse c"",
target_specific_cpu_args orelse "",
target_specific_cpu_features orelse "",
opt_level,
reloc_mode,
llvm.CodeModelDefault,

View File

@ -331,7 +331,7 @@ pub const Inst = struct {
@intCast(c_uint, args.len),
llvm_cc,
fn_inline,
c"",
"",
) orelse error.OutOfMemory;
}
};
@ -1410,7 +1410,7 @@ pub const Builder = struct {
if (block.label) |label| {
block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena());
block_scope.incoming_blocks = std.ArrayList(*BasicBlock).init(irb.arena());
block_scope.end_block = try irb.createBasicBlock(parent_scope, c"BlockEnd");
block_scope.end_block = try irb.createBasicBlock(parent_scope, "BlockEnd");
block_scope.is_comptime = try irb.buildConstBool(
parent_scope,
Span.token(block.lbrace),
@ -1542,8 +1542,8 @@ pub const Builder = struct {
const defer_counts = irb.countDefers(scope, outer_scope);
const have_err_defers = defer_counts.error_exit != 0;
if (have_err_defers or irb.comp.have_err_ret_tracing) {
const err_block = try irb.createBasicBlock(scope, c"ErrRetErr");
const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk");
const err_block = try irb.createBasicBlock(scope, "ErrRetErr");
const ok_block = try irb.createBasicBlock(scope, "ErrRetOk");
if (!have_err_defers) {
_ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable);
}
@ -1564,7 +1564,7 @@ pub const Builder = struct {
.is_comptime = err_is_comptime,
});
const ret_stmt_block = try irb.createBasicBlock(scope, c"RetStmt");
const ret_stmt_block = try irb.createBasicBlock(scope, "RetStmt");
try irb.setCursorAtEndAndAppendBlock(err_block);
if (have_err_defers) {
@ -2530,7 +2530,7 @@ pub async fn gen(
var irb = try Builder.init(comp, tree_scope, scope);
errdefer irb.abort();
const entry_block = try irb.createBasicBlock(scope, c"Entry");
const entry_block = try irb.createBasicBlock(scope, "Entry");
entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
try irb.setCursorAtEndAndAppendBlock(entry_block);

View File

@ -55,7 +55,7 @@ pub async fn link(comp: *Compilation) !void {
// even though we're calling LLD as a library it thinks the first
// argument is its own exe name
try ctx.args.append(c"lld");
try ctx.args.append("lld");
if (comp.haveLibC()) {
ctx.libc = ctx.comp.override_libc orelse blk: {
@ -145,7 +145,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// lj->args.append("-T");
// lj->args.append(g->linker_script);
//}
try ctx.args.append(c"--gc-sections");
try ctx.args.append("--gc-sections");
//lj->args.append("-m");
//lj->args.append(getLDMOption(&g->zig_target));
@ -155,9 +155,9 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
//Buf *soname = nullptr;
if (ctx.comp.is_static) {
if (ctx.comp.target.isArmOrThumb()) {
try ctx.args.append(c"-Bstatic");
try ctx.args.append("-Bstatic");
} else {
try ctx.args.append(c"-static");
try ctx.args.append("-static");
}
}
//} else if (shared) {
@ -170,7 +170,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize "", buf_ptr(g->root_out_name), g->version_major);
//}
try ctx.args.append(c"-o");
try ctx.args.append("-o");
try ctx.args.append(ctx.out_file_path.ptr());
if (ctx.link_in_crt) {
@ -213,10 +213,10 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
//}
if (ctx.comp.haveLibC()) {
try ctx.args.append(c"-L");
try ctx.args.append("-L");
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.lib_dir.?)).ptr);
try ctx.args.append(c"-L");
try ctx.args.append("-L");
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
if (!ctx.comp.is_static) {
@ -225,7 +225,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl;
return error.LibCMissingDynamicLinker;
};
try ctx.args.append(c"-dynamic-linker");
try ctx.args.append("-dynamic-linker");
try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
}
}
@ -272,23 +272,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// libc dep
if (ctx.comp.haveLibC()) {
if (ctx.comp.is_static) {
try ctx.args.append(c"--start-group");
try ctx.args.append(c"-lgcc");
try ctx.args.append(c"-lgcc_eh");
try ctx.args.append(c"-lc");
try ctx.args.append(c"-lm");
try ctx.args.append(c"--end-group");
try ctx.args.append("--start-group");
try ctx.args.append("-lgcc");
try ctx.args.append("-lgcc_eh");
try ctx.args.append("-lc");
try ctx.args.append("-lm");
try ctx.args.append("--end-group");
} else {
try ctx.args.append(c"-lgcc");
try ctx.args.append(c"--as-needed");
try ctx.args.append(c"-lgcc_s");
try ctx.args.append(c"--no-as-needed");
try ctx.args.append(c"-lc");
try ctx.args.append(c"-lm");
try ctx.args.append(c"-lgcc");
try ctx.args.append(c"--as-needed");
try ctx.args.append(c"-lgcc_s");
try ctx.args.append(c"--no-as-needed");
try ctx.args.append("-lgcc");
try ctx.args.append("--as-needed");
try ctx.args.append("-lgcc_s");
try ctx.args.append("--no-as-needed");
try ctx.args.append("-lc");
try ctx.args.append("-lm");
try ctx.args.append("-lgcc");
try ctx.args.append("--as-needed");
try ctx.args.append("-lgcc_s");
try ctx.args.append("--no-as-needed");
}
}
@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
}
if (ctx.comp.target != Target.Native) {
try ctx.args.append(c"--allow-shlib-undefined");
try ctx.args.append("--allow-shlib-undefined");
}
if (ctx.comp.target.getOs() == .zen) {
try ctx.args.append(c"-e");
try ctx.args.append(c"_start");
try ctx.args.append("-e");
try ctx.args.append("_start");
try ctx.args.append(c"--image-base=0x10000000");
try ctx.args.append("--image-base=0x10000000");
}
}
@ -317,23 +317,23 @@ fn addPathJoin(ctx: *Context, dirname: []const u8, basename: []const u8) !void {
}
fn constructLinkerArgsCoff(ctx: *Context) !void {
try ctx.args.append(c"-NOLOGO");
try ctx.args.append("-NOLOGO");
if (!ctx.comp.strip) {
try ctx.args.append(c"-DEBUG");
try ctx.args.append("-DEBUG");
}
switch (ctx.comp.target.getArch()) {
builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),
builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
builtin.Arch.i386 => try ctx.args.append("-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append("-MACHINE:X64"),
builtin.Arch.aarch64 => try ctx.args.append("-MACHINE:ARM"),
else => return error.UnsupportedLinkArchitecture,
}
if (ctx.comp.windows_subsystem_windows) {
try ctx.args.append(c"/SUBSYSTEM:windows");
try ctx.args.append("/SUBSYSTEM:windows");
} else if (ctx.comp.windows_subsystem_console) {
try ctx.args.append(c"/SUBSYSTEM:console");
try ctx.args.append("/SUBSYSTEM:console");
}
const is_library = ctx.comp.kind == Compilation.Kind.Lib;
@ -367,14 +367,14 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
// Visual C++ 2015 Conformance Changes
// https://msdn.microsoft.com/en-us/library/bb531344.aspx
try ctx.args.append(c"legacy_stdio_definitions.lib");
try ctx.args.append("legacy_stdio_definitions.lib");
// msvcrt depends on kernel32
try ctx.args.append(c"kernel32.lib");
try ctx.args.append("kernel32.lib");
} else {
try ctx.args.append(c"-NODEFAULTLIB");
try ctx.args.append("-NODEFAULTLIB");
if (!is_library) {
try ctx.args.append(c"-ENTRY:WinMainCRTStartup");
try ctx.args.append("-ENTRY:WinMainCRTStartup");
// TODO
//if (g->have_winmain) {
// lj->args.append("-ENTRY:WinMain");
@ -385,7 +385,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
}
if (is_library and !ctx.comp.is_static) {
try ctx.args.append(c"-DLL");
try ctx.args.append("-DLL");
}
//for (size_t i = 0; i < g->lib_dirs.length; i += 1) {
@ -463,18 +463,18 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
}
fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-demangle");
try ctx.args.append("-demangle");
if (ctx.comp.linker_rdynamic) {
try ctx.args.append(c"-export_dynamic");
try ctx.args.append("-export_dynamic");
}
const is_lib = ctx.comp.kind == Compilation.Kind.Lib;
const shared = !ctx.comp.is_static and is_lib;
if (ctx.comp.is_static) {
try ctx.args.append(c"-static");
try ctx.args.append("-static");
} else {
try ctx.args.append(c"-dynamic");
try ctx.args.append("-dynamic");
}
//if (is_lib) {
@ -503,7 +503,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
// }
//}
try ctx.args.append(c"-arch");
try ctx.args.append("-arch");
const darwin_arch_str = try std.cstr.addNullByte(
&ctx.arena.allocator,
ctx.comp.target.getDarwinArchString(),
@ -512,22 +512,22 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
const platform = try DarwinPlatform.get(ctx.comp);
switch (platform.kind) {
DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"),
DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"),
DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_version_min"),
DarwinPlatform.Kind.MacOS => try ctx.args.append("-macosx_version_min"),
DarwinPlatform.Kind.IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append("-ios_simulator_version_min"),
}
const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
try ctx.args.append(ver_str.ptr);
if (ctx.comp.kind == Compilation.Kind.Exe) {
if (ctx.comp.is_static) {
try ctx.args.append(c"-no_pie");
try ctx.args.append("-no_pie");
} else {
try ctx.args.append(c"-pie");
try ctx.args.append("-pie");
}
}
try ctx.args.append(c"-o");
try ctx.args.append("-o");
try ctx.args.append(ctx.out_file_path.ptr());
//for (size_t i = 0; i < g->rpath_list.length; i += 1) {
@ -537,27 +537,27 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
//add_rpath(lj, &lj->out_file);
if (shared) {
try ctx.args.append(c"-headerpad_max_install_names");
try ctx.args.append("-headerpad_max_install_names");
} else if (ctx.comp.is_static) {
try ctx.args.append(c"-lcrt0.o");
try ctx.args.append("-lcrt0.o");
} else {
switch (platform.kind) {
DarwinPlatform.Kind.MacOS => {
if (platform.versionLessThan(10, 5)) {
try ctx.args.append(c"-lcrt1.o");
try ctx.args.append("-lcrt1.o");
} else if (platform.versionLessThan(10, 6)) {
try ctx.args.append(c"-lcrt1.10.5.o");
try ctx.args.append("-lcrt1.10.5.o");
} else if (platform.versionLessThan(10, 8)) {
try ctx.args.append(c"-lcrt1.10.6.o");
try ctx.args.append("-lcrt1.10.6.o");
}
},
DarwinPlatform.Kind.IPhoneOS => {
if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
// iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) {
try ctx.args.append(c"-lcrt1.o");
try ctx.args.append("-lcrt1.o");
} else if (platform.versionLessThan(6, 0)) {
try ctx.args.append(c"-lcrt1.3.1.o");
try ctx.args.append("-lcrt1.3.1.o");
}
},
DarwinPlatform.Kind.IPhoneOSSimulator => {}, // no crt1.o needed
@ -589,7 +589,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
// to make syscalls because the syscall numbers are not documented
// and change between versions.
// so we always link against libSystem
try ctx.args.append(c"-lSystem");
try ctx.args.append("-lSystem");
} else {
if (mem.indexOfScalar(u8, lib.name, '/') == null) {
const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
@ -601,15 +601,15 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
}
}
} else {
try ctx.args.append(c"-undefined");
try ctx.args.append(c"dynamic_lookup");
try ctx.args.append("-undefined");
try ctx.args.append("dynamic_lookup");
}
if (platform.kind == DarwinPlatform.Kind.MacOS) {
if (platform.versionLessThan(10, 5)) {
try ctx.args.append(c"-lgcc_s.10.4");
try ctx.args.append("-lgcc_s.10.4");
} else if (platform.versionLessThan(10, 6)) {
try ctx.args.append(c"-lgcc_s.10.5");
try ctx.args.append("-lgcc_s.10.5");
}
} else {
@panic("TODO");

View File

@ -28,7 +28,7 @@ comptime {
// ABI warning
export fn stage2_zen(ptr: *[*]const u8, len: *usize) void {
const info_zen = @import("main.zig").info_zen;
ptr.* = &info_zen;
ptr.* = info_zen;
len.* = info_zen.len;
}

View File

@ -474,7 +474,7 @@ pub const Value = struct {
dont_null_terminate,
) orelse return error.OutOfMemory;
const str_init_type = llvm.TypeOf(llvm_str_init);
const global = llvm.AddGlobal(ofile.module, str_init_type, c"") orelse return error.OutOfMemory;
const global = llvm.AddGlobal(ofile.module, str_init_type, "") orelse return error.OutOfMemory;
llvm.SetInitializer(global, llvm_str_init);
llvm.SetLinkage(global, llvm.PrivateLinkage);
llvm.SetGlobalConstant(global, 1);

View File

@ -102,6 +102,10 @@ struct IrExecutable {
bool is_inline;
bool is_generic_instantiation;
bool need_err_code_spill;
// This is a function for use in the debugger to print
// the source location.
void src();
};
enum OutType {
@ -237,9 +241,6 @@ struct ConstPtrValue {
struct {
ConstExprValue *array_val;
size_t elem_index;
// This helps us preserve the null byte when performing compile-time
// concatenation on C strings.
bool is_cstr;
} base_array;
struct {
ConstExprValue *struct_val;
@ -1001,7 +1002,6 @@ struct AstNodeStructField {
struct AstNodeStringLiteral {
Buf *buf;
bool c;
};
struct AstNodeCharLiteral {
@ -1956,6 +1956,7 @@ struct CodeGen {
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table;
HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> type_info_cache;
HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> one_possible_values;
ZigList<Tld *> resolve_queue;
size_t resolve_queue_index;

View File

@ -767,10 +767,18 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size, bo
ZigType *entry = new_type_table_entry(ZigTypeIdArray);
buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
const char *null_str = is_null_terminated ? "null " : "";
buf_resize(&entry->name, 0);
buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s%s", array_size, null_str, buf_ptr(&child_type->name));
size_t full_array_size;
if (array_size == 0) {
full_array_size = 0;
} else {
full_array_size = array_size + (is_null_terminated ? 1 : 0);
}
size_t full_array_size = array_size + (is_null_terminated ? 1 : 0);
entry->size_in_bits = child_type->size_in_bits * full_array_size;
entry->abi_align = child_type->abi_align;
entry->abi_size = child_type->abi_size * full_array_size;
@ -5046,7 +5054,6 @@ static uint32_t hash_const_val_ptr(ConstExprValue *const_val) {
hash_val += (uint32_t)1764906839;
hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val);
hash_val += hash_size(const_val->data.x_ptr.data.base_array.elem_index);
hash_val += const_val->data.x_ptr.data.base_array.is_cstr ? 1297263887 : 200363492;
return hash_val;
case ConstPtrSpecialBaseStruct:
hash_val += (uint32_t)3518317043;
@ -5550,6 +5557,18 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
zig_unreachable();
}
ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
auto entry = g->one_possible_values.maybe_get(type_entry);
if (entry != nullptr) {
return entry->value;
}
ConstExprValue *result = create_const_vals(1);
result->type = type_entry;
result->special = ConstValSpecialStatic;
g->one_possible_values.put(type_entry, result);
return result;
}
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err;
switch (ty->id) {
@ -5617,10 +5636,19 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
return;
}
// first we build the underlying array
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
array_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), true);
array_val->data.x_array.special = ConstArraySpecialBuf;
array_val->data.x_array.data.s_buf = str;
// then make the pointer point to it
const_val->special = ConstValSpecialStatic;
const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), false);
const_val->data.x_array.special = ConstArraySpecialBuf;
const_val->data.x_array.data.s_buf = str;
const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);
const_val->data.x_ptr.special = ConstPtrSpecialRef;
const_val->data.x_ptr.data.ref.pointee = array_val;
g->string_literals_table.put(str, const_val);
}
@ -5631,41 +5659,6 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
return const_val;
}
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
// first we build the underlying array
size_t len_with_null = buf_len(str) + 1;
ConstExprValue *array_val = create_const_vals(1);
array_val->special = ConstValSpecialStatic;
array_val->type = get_array_type(g, g->builtin_types.entry_u8, len_with_null, false);
// TODO buf optimization
array_val->data.x_array.data.s_none.elements = create_const_vals(len_with_null);
for (size_t i = 0; i < buf_len(str); i += 1) {
ConstExprValue *this_char = &array_val->data.x_array.data.s_none.elements[i];
this_char->special = ConstValSpecialStatic;
this_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&this_char->data.x_bigint, (uint8_t)buf_ptr(str)[i]);
}
ConstExprValue *null_char = &array_val->data.x_array.data.s_none.elements[len_with_null - 1];
null_char->special = ConstValSpecialStatic;
null_char->type = g->builtin_types.entry_u8;
bigint_init_unsigned(&null_char->data.x_bigint, 0);
// then make the pointer point to it
const_val->special = ConstValSpecialStatic;
// TODO make this `[*]null u8` instead of `[*]u8`
const_val->type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
PtrLenUnknown, 0, 0, 0, false);
const_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
const_val->data.x_ptr.data.base_array.array_val = array_val;
const_val->data.x_ptr.data.base_array.elem_index = 0;
const_val->data.x_ptr.data.base_array.is_cstr = true;
}
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *str) {
ConstExprValue *const_val = create_const_vals(1);
init_const_c_str_lit(g, const_val, str);
return const_val;
}
void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
@ -5712,6 +5705,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {
return const_val;
}
void init_const_null(ConstExprValue *const_val, ZigType *type) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
const_val->data.x_optional = nullptr;
}
ConstExprValue *create_const_null(ZigType *type) {
ConstExprValue *const_val = create_const_vals(1);
init_const_null(const_val, type);
return const_val;
}
void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
@ -6446,8 +6451,6 @@ bool ir_get_var_is_comptime(ZigVar *var) {
bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_ptr.special != b->data.x_ptr.special)
return false;
if (a->data.x_ptr.mut != b->data.x_ptr.mut)
return false;
switch (a->data.x_ptr.special) {
case ConstPtrSpecialInvalid:
zig_unreachable();
@ -6464,8 +6467,6 @@ bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
}
if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
return false;
if (a->data.x_ptr.data.base_array.is_cstr != b->data.x_ptr.data.base_array.is_cstr)
return false;
return true;
case ConstPtrSpecialBaseStruct:
if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val &&
@ -6544,6 +6545,16 @@ bool const_values_equal(CodeGen *g, ConstExprValue *a, ConstExprValue *b) {
assert(a->type->id == b->type->id);
assert(a->special == ConstValSpecialStatic);
assert(b->special == ConstValSpecialStatic);
if (a->type == b->type) {
switch (type_has_one_possible_value(g, a->type)) {
case OnePossibleValueInvalid:
zig_unreachable();
case OnePossibleValueNo:
break;
case OnePossibleValueYes:
return true;
}
}
switch (a->type->id) {
case ZigTypeIdOpaque:
zig_unreachable();
@ -6709,15 +6720,10 @@ static void render_const_val_ptr(CodeGen *g, Buf *buf, ConstExprValue *const_val
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
case ConstPtrSpecialBaseArray:
if (const_val->data.x_ptr.data.base_array.is_cstr) {
buf_appendf(buf, "*(c str lit)");
return;
} else {
buf_appendf(buf, "*");
// TODO we need a source node for const_ptr_pointee because it can generate compile errors
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
}
buf_appendf(buf, "*");
// TODO we need a source node for const_ptr_pointee because it can generate compile errors
render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return;
case ConstPtrSpecialHardCodedAddr:
buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
const_val->data.x_ptr.data.hard_coded_addr.addr);
@ -8653,14 +8659,16 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) {
ZigType *elem_type = type->data.array.child_type;
uint64_t extra_len_from_null = type->data.array.is_null_terminated ? 1 : 0;
uint64_t full_len = type->data.array.len + extra_len_from_null;
// TODO https://github.com/ziglang/zig/issues/1424
type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)type->data.array.len);
type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)full_len);
uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type);
uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type);
type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits,
debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len);
debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)full_len);
}
static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
@ -9150,3 +9158,24 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
*out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
return ErrorNone;
}
void IrExecutable::src() {
IrExecutable *it;
for (it = this; it != nullptr && it->source_node != nullptr; it = it->parent_exec) {
it->source_node->src();
}
}
ConstExprValue *get_null_value(ZigType *ty) {
if (ty->id == ZigTypeIdInt || ty->id == ZigTypeIdComptimeInt) {
return create_const_unsigned_negative(ty, 0, false);
} else if (ty->id == ZigTypeIdFloat || ty->id == ZigTypeIdComptimeFloat) {
return create_const_float(ty, NAN);
} else if (ty->id == ZigTypeIdOptional) {
return create_const_null(ty);
} else {
zig_unreachable();
}
}

View File

@ -126,9 +126,6 @@ ScopeExpr *create_expr_scope(CodeGen *g, AstNode *node, Scope *parent);
void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str);
void init_const_c_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *c_str);
ConstExprValue *create_const_c_str_lit(CodeGen *g, Buf *c_str);
void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
ConstExprValue *create_const_bigint(ZigType *type, const BigInt *bigint);
@ -176,6 +173,9 @@ ConstExprValue *create_const_slice(CodeGen *g, ConstExprValue *array_val, size_t
void init_const_arg_tuple(CodeGen *g, ConstExprValue *const_val, size_t arg_index_start, size_t arg_index_end);
ConstExprValue *create_const_arg_tuple(CodeGen *g, size_t arg_index_start, size_t arg_index_end);
void init_const_null(ConstExprValue *const_val, ZigType *type);
ConstExprValue *create_const_null(ZigType *type);
ConstExprValue *create_const_vals(size_t count);
ConstExprValue **alloc_const_vals_ptrs(size_t count);
ConstExprValue **realloc_const_vals_ptrs(ConstExprValue **ptr, size_t old_count, size_t new_count);
@ -275,5 +275,6 @@ IrInstruction *ir_create_alloca(CodeGen *g, Scope *scope, AstNode *source_node,
ZigType *var_type, const char *name_hint);
Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path);
ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry);
ConstExprValue *get_null_value(ZigType *ty);
#endif

View File

@ -619,9 +619,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
break;
case NodeTypeStringLiteral:
{
if (node->data.string_literal.c) {
fprintf(ar->f, "c");
}
Buf tmp_buf = BUF_INIT;
string_literal_escape(node->data.string_literal.buf, &tmp_buf);
fprintf(ar->f, "\"%s\"", buf_ptr(&tmp_buf));

View File

@ -949,7 +949,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
if (!val->global_refs->llvm_global) {
Buf *buf_msg = panic_msg_buf(msg_id);
ConstExprValue *array_val = create_const_str_lit(g, buf_msg);
ConstExprValue *array_val = create_const_str_lit(g, buf_msg)->data.x_ptr.data.ref.pointee;
init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);
render_const_val(g, val, "");
@ -2784,14 +2784,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
IrInstruction *op1 = bin_op_instruction->op1;
IrInstruction *op2 = bin_op_instruction->op2;
assert(op1->value.type == op2->value.type || op_id == IrBinOpBitShiftLeftLossy ||
op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
op_id == IrBinOpBitShiftRightExact ||
(op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
(op1->value.type->id == ZigTypeIdPointer &&
(op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
op1->value.type->data.pointer.ptr_len != PtrLenSingle)
);
ZigType *operand_type = op1->value.type;
ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
@ -2848,7 +2840,6 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
AddSubMulMul;
if (scalar_type->id == ZigTypeIdPointer) {
assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
LLVMValueRef subscript_value;
if (operand_type->id == ZigTypeIdVector)
zig_panic("TODO: Implement vector operations on pointers.");
@ -3077,7 +3068,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
case CastOpNumLitToConcrete:
zig_unreachable();
case CastOpNoop:
return expr_val;
if (actual_type->id == ZigTypeIdPointer && wanted_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray &&
wanted_type->data.pointer.child_type->id == ZigTypeIdArray)
{
return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), "");
} else {
return expr_val;
}
case CastOpIntToFloat:
assert(actual_type->id == ZigTypeIdInt);
if (actual_type->data.integral.is_signed) {
@ -3709,8 +3707,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI
array_type = array_type->data.pointer.child_type;
}
if (safety_check_on) {
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type,
array_type->data.array.len, false);
uint64_t extra_len_from_null = array_type->data.array.is_null_terminated ? 1 : 0;
uint64_t full_len = array_type->data.array.len + extra_len_from_null;
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, full_len, false);
add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
}
if (array_ptr_type->data.pointer.host_int_bytes != 0) {
@ -6637,11 +6636,20 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con
ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
assert(array_const_val->type->id == ZigTypeIdArray);
if (!type_has_bits(array_const_val->type)) {
// make this a null pointer
ZigType *usize = g->builtin_types.entry_usize;
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
get_llvm_type(g, const_val->type));
return const_val->global_refs->llvm_value;
if (array_const_val->type->data.array.is_null_terminated) {
ConstExprValue *pointee = get_null_value(array_const_val->type->data.array.child_type);
render_const_val(g, pointee, "");
render_const_val_global(g, pointee, "");
const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global,
get_llvm_type(g, const_val->type));
return const_val->global_refs->llvm_value;
} else {
// make this a null pointer
ZigType *usize = g->builtin_types.entry_usize;
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
get_llvm_type(g, const_val->type));
return const_val->global_refs->llvm_value;
}
}
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index;
LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
@ -6955,7 +6963,9 @@ check: switch (const_val->special) {
case ConstArraySpecialUndef:
return LLVMGetUndef(get_llvm_type(g, type_entry));
case ConstArraySpecialNone: {
LLVMValueRef *values = allocate<LLVMValueRef>(len);
uint64_t extra_len_from_null = type_entry->data.array.is_null_terminated ? 1 : 0;
uint64_t full_len = len + extra_len_from_null;
LLVMValueRef *values = allocate<LLVMValueRef>(full_len);
LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
bool make_unnamed_struct = false;
for (uint64_t i = 0; i < len; i += 1) {
@ -6964,15 +6974,19 @@ check: switch (const_val->special) {
values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val);
}
if (type_entry->data.array.is_null_terminated) {
values[len] = LLVMConstNull(element_type_ref);
}
if (make_unnamed_struct) {
return LLVMConstStruct(values, len, true);
return LLVMConstStruct(values, full_len, true);
} else {
return LLVMConstArray(element_type_ref, values, (unsigned)len);
return LLVMConstArray(element_type_ref, values, (unsigned)full_len);
}
}
case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf;
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf), true);
return LLVMConstString(buf_ptr(buf), (unsigned)buf_len(buf),
!type_entry->data.array.is_null_terminated);
}
}
zig_unreachable();
@ -9092,7 +9106,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
this_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
ConstExprValue *name_field = this_val->data.x_struct.fields[0];
ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name);
ConstExprValue *name_array_val = create_const_str_lit(g, &test_fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
init_const_slice(g, name_field, name_array_val, 0, buf_len(&test_fn_entry->symbol_name), true);
ConstExprValue *fn_field = this_val->data.x_struct.fields[1];
@ -10415,6 +10429,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
g->external_prototypes.init(8);
g->string_literals_table.init(16);
g->type_info_cache.init(32);
g->one_possible_values.init(32);
g->is_test_build = is_test_build;
g->is_single_threaded = false;
buf_resize(&g->global_asm, 0);

View File

@ -66,6 +66,8 @@ enum ConstCastResultId {
ConstCastResultIdUnresolvedInferredErrSet,
ConstCastResultIdAsyncAllocatorType,
ConstCastResultIdBadAllowsZero,
ConstCastResultIdArrayChild,
ConstCastResultIdBadNullTermArrays,
};
struct ConstCastOnly;
@ -87,7 +89,9 @@ struct ConstCastErrUnionErrSetMismatch;
struct ConstCastErrUnionPayloadMismatch;
struct ConstCastErrSetMismatch;
struct ConstCastTypeMismatch;
struct ConstCastArrayMismatch;
struct ConstCastBadAllowsZero;
struct ConstCastBadNullTermArrays;
struct ConstCastOnly {
ConstCastResultId id;
@ -99,11 +103,13 @@ struct ConstCastOnly {
ConstCastErrUnionPayloadMismatch *error_union_payload;
ConstCastErrUnionErrSetMismatch *error_union_error_set;
ConstCastTypeMismatch *type_mismatch;
ConstCastArrayMismatch *array_mismatch;
ConstCastOnly *return_type;
ConstCastOnly *null_wrap_ptr_child;
ConstCastArg fn_arg;
ConstCastArgNoAlias arg_no_alias;
ConstCastBadAllowsZero *bad_allows_zero;
ConstCastBadNullTermArrays *bad_null_term_arrays;
} data;
};
@ -130,6 +136,12 @@ struct ConstCastSliceMismatch {
ZigType *actual_child;
};
struct ConstCastArrayMismatch {
ConstCastOnly child;
ZigType *wanted_child;
ZigType *actual_child;
};
struct ConstCastErrUnionErrSetMismatch {
ConstCastOnly child;
ZigType *wanted_err_set;
@ -151,6 +163,12 @@ struct ConstCastBadAllowsZero {
ZigType *actual_type;
};
struct ConstCastBadNullTermArrays {
ConstCastOnly child;
ZigType *wanted_type;
ZigType *actual_type;
};
static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope);
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval,
@ -217,10 +235,7 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
case OnePossibleValueInvalid:
zig_unreachable();
case OnePossibleValueYes:
result = create_const_vals(1);
result->type = const_val->type->data.pointer.child_type;
result->special = ConstValSpecialStatic;
return result;
return get_the_one_possible_value(g, const_val->type->data.pointer.child_type);
case OnePossibleValueNo:
break;
}
@ -233,8 +248,13 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
break;
case ConstPtrSpecialBaseArray: {
ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
expand_undef_array(g, array_val);
result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
if (const_val->data.x_ptr.data.base_array.elem_index == array_val->type->data.array.len) {
assert(array_val->type->data.array.is_null_terminated);
result = get_null_value(array_val->type->data.array.child_type);
} else {
expand_undef_array(g, array_val);
result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
}
break;
}
case ConstPtrSpecialBaseStruct: {
@ -282,20 +302,20 @@ static bool slice_is_const(ZigType *type) {
// This function returns true when you can change the type of a ConstExprValue and the
// value remains meaningful.
static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
if (a == b)
static bool types_have_same_zig_comptime_repr(ZigType *expected, ZigType *actual) {
if (expected == actual)
return true;
if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
if (get_codegen_ptr_type(expected) != nullptr && get_codegen_ptr_type(actual) != nullptr)
return true;
if (is_opt_err_set(a) && is_opt_err_set(b))
if (is_opt_err_set(expected) && is_opt_err_set(actual))
return true;
if (a->id != b->id)
if (expected->id != actual->id)
return false;
switch (a->id) {
switch (expected->id) {
case ZigTypeIdInvalid:
case ZigTypeIdUnreachable:
zig_unreachable();
@ -314,12 +334,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdAnyFrame:
return true;
case ZigTypeIdFloat:
return a->data.floating.bit_count == b->data.floating.bit_count;
return expected->data.floating.bit_count == actual->data.floating.bit_count;
case ZigTypeIdInt:
return a->data.integral.is_signed == b->data.integral.is_signed;
return expected->data.integral.is_signed == actual->data.integral.is_signed;
case ZigTypeIdStruct:
return is_slice(a) && is_slice(b);
case ZigTypeIdArray:
return is_slice(expected) && is_slice(actual);
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdEnum:
@ -329,6 +348,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdVector:
case ZigTypeIdFnFrame:
return false;
case ZigTypeIdArray:
return expected->data.array.len == actual->data.array.len &&
expected->data.array.child_type == actual->data.array.child_type &&
(!expected->data.array.is_null_terminated || actual->data.array.is_null_terminated);
}
zig_unreachable();
}
@ -1299,12 +1322,6 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo
return instruction;
}
static IrInstruction *ir_build_const_c_str_lit(IrBuilder *irb, Scope *scope, AstNode *source_node, Buf *str) {
IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
init_const_c_str_lit(irb->codegen, &const_instruction->base.value, str);
return &const_instruction->base;
}
static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
IrInstruction *op1, IrInstruction *op2, bool safety_check_on)
{
@ -6932,11 +6949,7 @@ static IrInstruction *ir_gen_enum_literal(IrBuilder *irb, Scope *scope, AstNode
static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeStringLiteral);
if (node->data.string_literal.c) {
return ir_build_const_c_str_lit(irb, scope, node, node->data.string_literal.buf);
} else {
return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf);
}
return ir_build_const_str_lit(irb, scope, node, node->data.string_literal.buf);
}
static IrInstruction *ir_gen_array_type(IrBuilder *irb, Scope *scope, AstNode *node) {
@ -8662,7 +8675,15 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
assert(val != nullptr);
assert(const_val->type->id == ZigTypeIdPointer);
ZigType *expected_type = const_val->type->data.pointer.child_type;
if (!types_have_same_zig_comptime_repr(val->type, expected_type)) {
switch (type_has_one_possible_value(codegen, expected_type)) {
case OnePossibleValueInvalid:
return nullptr;
case OnePossibleValueNo:
break;
case OnePossibleValueYes:
return get_the_one_possible_value(codegen, expected_type);
}
if (!types_have_same_zig_comptime_repr(expected_type, val->type)) {
if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
return nullptr;
return const_ptr_pointee_unchecked(codegen, const_val);
@ -9876,6 +9897,35 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
}
}
// arrays
if (wanted_type->id == ZigTypeIdArray && actual_type->id == ZigTypeIdArray &&
wanted_type->data.array.len == actual_type->data.array.len)
{
ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.array.child_type,
actual_type->data.array.child_type, source_node, wanted_is_mutable);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdArrayChild;
result.data.array_mismatch = allocate_nonzero<ConstCastArrayMismatch>(1);
result.data.array_mismatch->child = child;
result.data.array_mismatch->wanted_child = wanted_type->data.array.child_type;
result.data.array_mismatch->actual_child = actual_type->data.array.child_type;
return result;
}
bool ok_null_terminated = !wanted_type->data.array.is_null_terminated ||
actual_type->data.array.is_null_terminated;
if (!ok_null_terminated) {
result.id = ConstCastResultIdBadNullTermArrays;
result.data.bad_null_term_arrays = allocate_nonzero<ConstCastBadNullTermArrays>(1);
result.data.bad_null_term_arrays->child = child;
result.data.bad_null_term_arrays->wanted_type = wanted_type;
result.data.bad_null_term_arrays->actual_type = actual_type;
return result;
}
return result;
}
// slice const
if (is_slice(wanted_type) && is_slice(actual_type)) {
ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry;
@ -10692,6 +10742,42 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
// *[N]T and *[M]T
if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
(cur_type->data.pointer.is_const || !prev_type->data.pointer.is_const ||
prev_type->data.pointer.child_type->data.array.len == 0) &&
(cur_type->data.pointer.child_type->data.array.is_null_terminated ||
!prev_type->data.pointer.child_type->data.array.is_null_terminated) &&
types_match_const_cast_only(ira,
cur_type->data.pointer.child_type->data.array.child_type,
prev_type->data.pointer.child_type->data.array.child_type,
source_node, !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
prev_inst = cur_inst;
convert_to_const_slice = true;
continue;
}
if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenSingle &&
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenSingle &&
cur_type->data.pointer.child_type->id == ZigTypeIdArray &&
(prev_type->data.pointer.is_const || !cur_type->data.pointer.is_const ||
cur_type->data.pointer.child_type->data.array.len == 0) &&
(prev_type->data.pointer.child_type->data.array.is_null_terminated ||
!cur_type->data.pointer.child_type->data.array.is_null_terminated) &&
types_match_const_cast_only(ira,
prev_type->data.pointer.child_type->data.array.child_type,
cur_type->data.pointer.child_type->data.array.child_type,
source_node, !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
convert_to_const_slice = true;
continue;
}
// [N]T to []T
if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&
(cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||
@ -10740,16 +10826,33 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
free(errors);
if (convert_to_const_slice) {
assert(prev_inst->value.type->id == ZigTypeIdArray);
ZigType *ptr_type = get_pointer_to_type_extra(
ira->codegen, prev_inst->value.type->data.array.child_type,
true, false, PtrLenUnknown,
0, 0, 0, false);
ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
if (err_set_type != nullptr) {
return get_error_union_type(ira->codegen, err_set_type, slice_type);
if (prev_inst->value.type->id == ZigTypeIdArray) {
ZigType *ptr_type = get_pointer_to_type_extra(
ira->codegen, prev_inst->value.type->data.array.child_type,
true, false, PtrLenUnknown,
0, 0, 0, false);
ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
if (err_set_type != nullptr) {
return get_error_union_type(ira->codegen, err_set_type, slice_type);
} else {
return slice_type;
}
} else if (prev_inst->value.type->id == ZigTypeIdPointer) {
ZigType *array_type = prev_inst->value.type->data.pointer.child_type;
src_assert(array_type->id == ZigTypeIdArray, source_node);
ZigType *ptr_type = get_pointer_to_type_extra(
ira->codegen, array_type->data.array.child_type,
prev_inst->value.type->data.pointer.is_const, false,
array_type->data.array.is_null_terminated ? PtrLenNull : PtrLenUnknown,
0, 0, 0, false);
ZigType *slice_type = get_slice_type(ira->codegen, ptr_type);
if (err_set_type != nullptr) {
return get_error_union_type(ira->codegen, err_set_type, slice_type);
} else {
return slice_type;
}
} else {
return slice_type;
zig_unreachable();
}
} else if (err_set_type != nullptr) {
if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
@ -10970,7 +11073,6 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
result->value.data.x_ptr.mut = value->value.data.x_ptr.mut;
result->value.data.x_ptr.data.base_array.array_val = pointee;
result->value.data.x_ptr.data.base_array.elem_index = 0;
result->value.data.x_ptr.data.base_array.is_cstr = false;
return result;
}
}
@ -10982,31 +11084,31 @@ static IrInstruction *ir_resolve_ptr_of_array_to_unknown_len_ptr(IrAnalyze *ira,
}
static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *value, ZigType *wanted_type, ResultLoc *result_loc)
IrInstruction *array_ptr, ZigType *wanted_type, ResultLoc *result_loc)
{
Error err;
if ((err = type_resolve(ira->codegen, value->value.type->data.pointer.child_type,
if ((err = type_resolve(ira->codegen, array_ptr->value.type->data.pointer.child_type,
ResolveStatusAlignmentKnown)))
{
return ira->codegen->invalid_instruction;
}
wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, value->value.type));
wanted_type = adjust_slice_align(ira->codegen, wanted_type, get_ptr_align(ira->codegen, array_ptr->value.type));
if (instr_is_comptime(value)) {
ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node);
if (instr_is_comptime(array_ptr)) {
ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &array_ptr->value, source_instr->source_node);
if (pointee == nullptr)
return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) {
assert(value->value.type->id == ZigTypeIdPointer);
ZigType *array_type = value->value.type->data.pointer.child_type;
assert(array_ptr->value.type->id == ZigTypeIdPointer);
ZigType *array_type = array_ptr->value.type->data.pointer.child_type;
assert(is_slice(wanted_type));
bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const;
IrInstruction *result = ir_const(ira, source_instr, wanted_type);
init_const_slice(ira->codegen, &result->value, pointee, 0, array_type->data.array.len, is_const);
result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = value->value.data.x_ptr.mut;
result->value.data.x_struct.fields[slice_ptr_index]->data.x_ptr.mut = array_ptr->value.data.x_ptr.mut;
result->value.type = wanted_type;
return result;
}
@ -11018,7 +11120,7 @@ static IrInstruction *ir_resolve_ptr_of_array_to_slice(IrAnalyze *ira, IrInstruc
if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return result_loc_inst;
}
return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, value, result_loc_inst);
return ir_build_ptr_of_array_to_slice(ira, source_instr, wanted_type, array_ptr, result_loc_inst);
}
static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
@ -12483,6 +12585,8 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
case ConstCastResultIdFnArgNoAlias: // TODO
case ConstCastResultIdUnresolvedInferredErrSet: // TODO
case ConstCastResultIdAsyncAllocatorType: // TODO
case ConstCastResultIdArrayChild: // TODO
case ConstCastResultIdBadNullTermArrays: // TODO
break;
}
}
@ -12795,7 +12899,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
}
// cast from [N]T to []const T
// TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
@ -12834,23 +12937,46 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
}
}
// *[N]T to [*]T and [*c]T
if (wanted_type->id == ZigTypeIdPointer &&
(wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) &&
// *[N]T to ?[]const T
if (wanted_type->id == ZigTypeIdOptional &&
is_slice(wanted_type->data.maybe.child_type) &&
actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray)
{
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
IrInstruction *cast1 = ir_analyze_cast(ira, source_instr, wanted_type->data.maybe.child_type, value, nullptr);
if (type_is_invalid(cast1->value.type))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
IrInstruction *cast2 = ir_analyze_cast(ira, source_instr, wanted_type, cast1, result_loc);
if (type_is_invalid(cast2->value.type))
return ira->codegen->invalid_instruction;
if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
return cast2;
}
// *[N]T to [*]T and [*c]T
if (wanted_type->id == ZigTypeIdPointer &&
(wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC ||
wanted_type->data.pointer.ptr_len == PtrLenNull) &&
actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray)
{
if (wanted_type->data.pointer.ptr_len != PtrLenNull ||
actual_type->data.pointer.child_type->data.array.is_null_terminated)
{
return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction;
if (get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type) &&
types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
actual_type->data.pointer.child_type->data.array.child_type, source_node,
!wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
{
return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
}
}
}
@ -14544,8 +14670,6 @@ static bool ok_float_op(IrBinOp op) {
}
static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
if (lhs_type->id != ZigTypeIdPointer)
return false;
switch (op) {
case IrBinOpAdd:
case IrBinOpSub:
@ -14553,15 +14677,17 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
default:
return false;
}
if (lhs_type->id != ZigTypeIdPointer)
return false;
switch (lhs_type->data.pointer.ptr_len) {
case PtrLenSingle:
return false;
return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;
case PtrLenUnknown:
case PtrLenNull:
case PtrLenC:
break;
return true;
}
return true;
zig_unreachable();
}
static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
@ -14823,6 +14949,7 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
if (!op2_val)
return ira->codegen->invalid_instruction;
bool is_null_terminated = false;
ConstExprValue *op1_array_val;
size_t op1_array_index;
size_t op1_array_end;
@ -14834,13 +14961,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op1_array_end = op1_type->data.array.len;
} else if (op1_type->id == ZigTypeIdPointer &&
op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
op1_val->data.x_ptr.data.base_array.is_cstr)
op1_type->data.pointer.ptr_len == PtrLenNull &&
op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
{
child_type = op1_type->data.pointer.child_type;
op1_array_val = op1_val->data.x_ptr.data.base_array.array_val;
op1_array_index = op1_val->data.x_ptr.data.base_array.elem_index;
op1_array_end = op1_array_val->type->data.array.len - 1;
op1_array_end = op1_array_val->type->data.array.len;
is_null_terminated = true;
} else if (is_slice(op1_type)) {
ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
child_type = ptr_type->data.pointer.child_type;
@ -14850,9 +14978,20 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op1_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
ConstExprValue *len_val = op1_val->data.x_struct.fields[slice_len_index];
op1_array_end = op1_array_index + bigint_as_usize(&len_val->data.x_bigint);
} else if (op1_type->id == ZigTypeIdPointer && op1_type->data.pointer.ptr_len == PtrLenSingle &&
op1_type->data.pointer.child_type->id == ZigTypeIdArray)
{
ZigType *array_type = op1_type->data.pointer.child_type;
child_type = array_type->data.array.child_type;
op1_array_val = const_ptr_pointee(ira, ira->codegen, op1_val, op1->source_node);
if (op1_array_val == nullptr)
return ira->codegen->invalid_instruction;
op1_array_index = 0;
op1_array_end = array_type->data.array.len;
is_null_terminated = is_null_terminated || array_type->data.array.is_null_terminated;
} else {
ir_add_error(ira, op1,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op1->value.type->name)));
buf_sprintf("expected array, found '%s'", buf_ptr(&op1->value.type->name)));
return ira->codegen->invalid_instruction;
}
@ -14866,14 +15005,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op2_array_index = 0;
op2_array_end = op2_array_val->type->data.array.len;
} else if (op2_type->id == ZigTypeIdPointer &&
op2_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray &&
op2_val->data.x_ptr.data.base_array.is_cstr)
op2_type->data.pointer.ptr_len == PtrLenNull &&
op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
{
op2_type_valid = child_type == ira->codegen->builtin_types.entry_u8;
op2_type_valid = op2_type->data.pointer.child_type == child_type;
op2_array_val = op2_val->data.x_ptr.data.base_array.array_val;
op2_array_index = op2_val->data.x_ptr.data.base_array.elem_index;
op2_array_end = op2_array_val->type->data.array.len - 1;
op2_array_end = op2_array_val->type->data.array.len;
is_null_terminated = true;
} else if (is_slice(op2_type)) {
ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
op2_type_valid = ptr_type->data.pointer.child_type == child_type;
@ -14883,6 +15022,17 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
op2_array_index = ptr_val->data.x_ptr.data.base_array.elem_index;
ConstExprValue *len_val = op2_val->data.x_struct.fields[slice_len_index];
op2_array_end = op2_array_index + bigint_as_usize(&len_val->data.x_bigint);
} else if (op2_type->id == ZigTypeIdPointer && op2_type->data.pointer.ptr_len == PtrLenSingle &&
op2_type->data.pointer.child_type->id == ZigTypeIdArray)
{
ZigType *array_type = op2_type->data.pointer.child_type;
op2_type_valid = array_type->data.array.child_type == child_type;
op2_array_val = const_ptr_pointee(ira, ira->codegen, op2_val, op2->source_node);
if (op2_array_val == nullptr)
return ira->codegen->invalid_instruction;
op2_array_index = 0;
op2_array_end = array_type->data.array.len;
is_null_terminated = is_null_terminated || array_type->data.array.is_null_terminated;
} else {
ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name)));
@ -14905,6 +15055,14 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
result->value.type = get_array_type(ira->codegen, child_type, new_len, false);
out_array_val = out_val;
} else if (op1_type->id == ZigTypeIdPointer || op2_type->id == ZigTypeIdPointer) {
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
out_array_val->type = get_array_type(ira->codegen, child_type, new_len, is_null_terminated);
out_val->data.x_ptr.special = ConstPtrSpecialRef;
out_val->data.x_ptr.data.ref.pointee = out_array_val;
out_val->type = get_pointer_to_type(ira->codegen, out_array_val->type, true);
} else if (is_slice(op1_type) || is_slice(op2_type)) {
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
true, false, PtrLenUnknown, 0, 0, 0, false);
@ -14925,22 +15083,20 @@ static IrInstruction *ir_analyze_array_cat(IrAnalyze *ira, IrInstructionBinOp *i
out_val->data.x_struct.fields[slice_len_index]->special = ConstValSpecialStatic;
bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
} else {
new_len += 1; // null byte
// TODO make this `[*]null T` instead of `[*]T`
result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenUnknown, 0, 0, 0, false);
result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenNull,
0, 0, 0, false);
out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic;
out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false);
out_val->data.x_ptr.special = ConstPtrSpecialBaseArray;
out_val->data.x_ptr.data.base_array.is_cstr = true;
out_val->data.x_ptr.data.base_array.array_val = out_array_val;
out_val->data.x_ptr.data.base_array.elem_index = 0;
}
if (op1_array_val->data.x_array.special == ConstArraySpecialUndef &&
op2_array_val->data.x_array.special == ConstArraySpecialUndef) {
op2_array_val->data.x_array.special == ConstArraySpecialUndef)
{
out_array_val->data.x_array.special = ConstArraySpecialUndef;
return result;
}
@ -14978,20 +15134,34 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
if (type_is_invalid(op2->value.type))
return ira->codegen->invalid_instruction;
ConstExprValue *array_val = ir_resolve_const(ira, op1, UndefBad);
if (!array_val)
bool want_ptr_to_array = false;
ZigType *array_type;
ConstExprValue *array_val;
if (op1->value.type->id == ZigTypeIdArray) {
array_type = op1->value.type;
array_val = ir_resolve_const(ira, op1, UndefOk);
if (array_val == nullptr)
return ira->codegen->invalid_instruction;
} else if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenSingle &&
op1->value.type->data.pointer.child_type->id == ZigTypeIdArray)
{
array_type = op1->value.type->data.pointer.child_type;
IrInstruction *array_inst = ir_get_deref(ira, op1, op1, nullptr);
if (type_is_invalid(array_inst->value.type))
return ira->codegen->invalid_instruction;
array_val = ir_resolve_const(ira, array_inst, UndefOk);
if (array_val == nullptr)
return ira->codegen->invalid_instruction;
want_ptr_to_array = true;
} else {
ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
return ira->codegen->invalid_instruction;
}
uint64_t mult_amt;
if (!ir_resolve_usize(ira, op2, &mult_amt))
return ira->codegen->invalid_instruction;
ZigType *array_type = op1->value.type;
if (array_type->id != ZigTypeIdArray) {
ir_add_error(ira, op1, buf_sprintf("expected array type, found '%s'", buf_ptr(&op1->value.type->name)));
return ira->codegen->invalid_instruction;
}
uint64_t old_array_len = array_type->data.array.len;
uint64_t new_array_len;
@ -15001,42 +15171,59 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
}
ZigType *child_type = array_type->data.array.child_type;
ZigType *result_array_type = get_array_type(ira->codegen, child_type, new_array_len,
array_type->data.array.is_null_terminated);
IrInstruction *result = ir_const(ira, &instruction->base,
get_array_type(ira->codegen, child_type, new_array_len, false));
ConstExprValue *out_val = &result->value;
if (array_val->data.x_array.special == ConstArraySpecialUndef) {
out_val->data.x_array.special = ConstArraySpecialUndef;
return result;
}
IrInstruction *array_result;
if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
array_result = ir_const_undef(ira, &instruction->base, result_array_type);
} else {
array_result = ir_const(ira, &instruction->base, result_array_type);
ConstExprValue *out_val = &array_result->value;
switch (type_has_one_possible_value(ira->codegen, result->value.type)) {
case OnePossibleValueInvalid:
return ira->codegen->invalid_instruction;
case OnePossibleValueYes:
return result;
case OnePossibleValueNo:
break;
}
switch (type_has_one_possible_value(ira->codegen, result_array_type)) {
case OnePossibleValueInvalid:
return ira->codegen->invalid_instruction;
case OnePossibleValueYes:
goto skip_computation;
case OnePossibleValueNo:
break;
}
// TODO optimize the buf case
expand_undef_array(ira->codegen, array_val);
out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len);
// TODO optimize the buf case
expand_undef_array(ira->codegen, array_val);
size_t extra_null_term = array_type->data.array.is_null_terminated ? 1 : 0;
out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len + extra_null_term);
uint64_t i = 0;
for (uint64_t x = 0; x < mult_amt; x += 1) {
for (uint64_t y = 0; y < old_array_len; y += 1) {
uint64_t i = 0;
for (uint64_t x = 0; x < mult_amt; x += 1) {
for (uint64_t y = 0; y < old_array_len; y += 1) {
ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
copy_const_val(elem_dest_val, &array_val->data.x_array.data.s_none.elements[y], false);
elem_dest_val->parent.id = ConstParentIdArray;
elem_dest_val->parent.data.p_array.array_val = out_val;
elem_dest_val->parent.data.p_array.elem_index = i;
i += 1;
}
}
assert(i == new_array_len);
if (array_type->data.array.is_null_terminated) {
ConstExprValue *null_value = get_null_value(array_type->data.array.child_type);
ConstExprValue *elem_dest_val = &out_val->data.x_array.data.s_none.elements[i];
copy_const_val(elem_dest_val, &array_val->data.x_array.data.s_none.elements[y], false);
copy_const_val(elem_dest_val, null_value, false);
elem_dest_val->parent.id = ConstParentIdArray;
elem_dest_val->parent.data.p_array.array_val = out_val;
elem_dest_val->parent.data.p_array.elem_index = i;
i += 1;
}
}
assert(i == new_array_len);
return result;
skip_computation:
if (want_ptr_to_array) {
return ir_get_ref(ira, &instruction->base, array_result, true, false);
} else {
return array_result;
}
}
static IrInstruction *ir_analyze_instruction_merge_err_sets(IrAnalyze *ira,
@ -17309,6 +17496,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
assert(out_val->type != nullptr);
ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
src_assert(pointee->type != nullptr, source_node);
if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
return ErrorSemanticAnalyzeFail;
@ -17319,7 +17507,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
size_t dst_size = type_size(codegen, out_val->type);
if (dst_size <= src_size) {
if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
if (src_size == dst_size && types_have_same_zig_comptime_repr(out_val->type, pointee->type)) {
copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
return ErrorNone;
}
@ -18070,6 +18258,12 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
if (array_type->id == ZigTypeIdArray) {
uint64_t array_len = array_type->data.array.len;
if (index == array_len && array_type->data.array.is_null_terminated) {
ZigType *elem_type = array_type->data.array.child_type;
IrInstruction *null_element = ir_const(ira, &elem_ptr_instruction->base, elem_type);
null_element->value = *get_null_value(elem_type);
return ir_get_ref(ira, &elem_ptr_instruction->base, null_element, true, false);
}
if (index >= array_len) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64,
@ -18203,7 +18397,11 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
{
size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
new_index = offset + index;
mem_size = array_ptr_val->data.x_ptr.data.base_array.array_val->type->data.array.len;
ZigType *array_type = array_ptr_val->data.x_ptr.data.base_array.array_val->type;
mem_size = array_type->data.array.len;
if (array_type->data.array.is_null_terminated) {
mem_size += 1;
}
old_size = mem_size - offset;
assert(array_ptr_val->data.x_ptr.data.base_array.array_val);
@ -18212,8 +18410,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
out_val->data.x_ptr.data.base_array.array_val =
array_ptr_val->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
array_ptr_val->data.x_ptr.data.base_array.is_cstr;
break;
}
@ -18277,8 +18473,6 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
out_val->data.x_ptr.data.base_array.array_val =
ptr_field->data.x_ptr.data.base_array.array_val;
out_val->data.x_ptr.data.base_array.elem_index = new_index;
out_val->data.x_ptr.data.base_array.is_cstr =
ptr_field->data.x_ptr.data.base_array.is_cstr;
break;
}
case ConstPtrSpecialBaseStruct:
@ -19550,7 +19744,7 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
bool same_comptime_repr = types_have_same_zig_comptime_repr(type_entry, child_type);
bool same_comptime_repr = types_have_same_zig_comptime_repr(child_type, type_entry);
if (instr_is_comptime(base_ptr)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad);
@ -20685,7 +20879,7 @@ static IrInstruction *ir_analyze_instruction_err_name(IrAnalyze *ira, IrInstruct
return ira->codegen->invalid_instruction;
ErrorTableEntry *err = casted_value->value.data.x_err_set;
if (!err->cached_error_name_val) {
ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name);
ConstExprValue *array_val = create_const_str_lit(ira->codegen, &err->name)->data.x_ptr.data.ref.pointee;
err->cached_error_name_val = create_const_slice(ira->codegen, array_val, 0, buf_len(&err->name), true);
}
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
@ -20714,7 +20908,7 @@ static IrInstruction *ir_analyze_instruction_enum_tag_name(IrAnalyze *ira, IrIns
if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction;
TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint);
ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name);
ConstExprValue *array_val = create_const_str_lit(ira->codegen, field->name)->data.x_ptr.data.ref.pointee;
IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);
return result;
@ -21019,7 +21213,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
declaration_val->type = type_info_declaration_type;
ConstExprValue **inner_fields = alloc_const_vals_ptrs(3);
ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key);
ConstExprValue *name = create_const_str_lit(ira->codegen, curr_entry->key)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true);
inner_fields[1]->special = ConstValSpecialStatic;
inner_fields[1]->type = ira->codegen->builtin_types.entry_bool;
@ -21122,7 +21316,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
fn_decl_fields[6]->type = get_optional_type(ira->codegen, get_slice_type(ira->codegen, u8_ptr));
if (fn_node->is_extern && fn_node->lib_name != nullptr && buf_len(fn_node->lib_name) > 0) {
fn_decl_fields[6]->data.x_optional = create_const_vals(1);
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name);
ConstExprValue *lib_name = create_const_str_lit(ira->codegen, fn_node->lib_name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0,
buf_len(fn_node->lib_name), true);
} else {
@ -21149,7 +21343,7 @@ static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr
ZigVar *arg_var = fn_entry->variable_list.at(fn_arg_index);
ConstExprValue *fn_arg_name_val = &fn_arg_name_array->data.x_array.data.s_none.elements[fn_arg_index];
ConstExprValue *arg_name = create_const_str_lit(ira->codegen,
buf_create_from_str(arg_var->name));
buf_create_from_str(arg_var->name))->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, fn_arg_name_val, arg_name, 0, strlen(arg_var->name), true);
fn_arg_name_val->parent.id = ConstParentIdArray;
fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array;
@ -21294,7 +21488,7 @@ static void make_enum_field_val(IrAnalyze *ira, ConstExprValue *enum_field_val,
inner_fields[1]->special = ConstValSpecialStatic;
inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int;
ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name);
ConstExprValue *name = create_const_str_lit(ira->codegen, enum_field->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(enum_field->name), true);
bigint_init_bigint(&inner_fields[1]->data.x_bigint, &enum_field->value);
@ -21560,7 +21754,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
if (error->cached_error_name_val != nullptr)
name = error->cached_error_name_val;
if (name == nullptr)
name = create_const_str_lit(ira->codegen, &error->name);
name = create_const_str_lit(ira->codegen, &error->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(&error->name), true);
bigint_init_unsigned(&inner_fields[1]->data.x_bigint, error->value);
@ -21666,7 +21860,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = union_field->type_entry;
ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name);
ConstExprValue *name = create_const_str_lit(ira->codegen, union_field->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(union_field->name), true);
union_field_val->data.x_struct.fields = inner_fields;
@ -21752,7 +21946,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
inner_fields[2]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = struct_field->type_entry;
ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name);
ConstExprValue *name = create_const_str_lit(ira->codegen, struct_field->name)->data.x_ptr.data.ref.pointee;
init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(struct_field->name), true);
struct_field_val->data.x_struct.fields = inner_fields;

View File

@ -1718,7 +1718,6 @@ static AstNode *ast_parse_primary_type_expr(ParseContext *pc) {
if (string_lit != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);
res->data.string_literal.buf = token_buf(string_lit);
res->data.string_literal.c = string_lit->data.str_lit.is_c_str;
return res;
}

View File

@ -33,10 +33,10 @@
'0': \
case DIGIT_NON_ZERO
#define ALPHA_EXCEPT_C \
#define ALPHA \
'a': \
case 'b': \
/*case 'c':*/ \
case 'c': \
case 'd': \
case 'e': \
case 'f': \
@ -87,10 +87,6 @@
case 'Y': \
case 'Z'
#define ALPHA \
ALPHA_EXCEPT_C: \
case 'c'
#define SYMBOL_CHAR \
ALPHA: \
case DIGIT: \
@ -180,7 +176,6 @@ static bool is_symbol_char(uint8_t c) {
enum TokenizeState {
TokenizeStateStart,
TokenizeStateSymbol,
TokenizeStateSymbolFirstC,
TokenizeStateZero, // "0", which might lead to "0x"
TokenizeStateNumber, // "123", "0x123"
TokenizeStateNumberDot,
@ -279,7 +274,6 @@ static void set_token_id(Tokenize *t, Token *token, TokenId id) {
} else if (id == TokenIdStringLiteral || id == TokenIdSymbol) {
memset(&token->data.str_lit.str, 0, sizeof(Buf));
buf_resize(&token->data.str_lit.str, 0);
token->data.str_lit.is_c_str = false;
}
}
@ -429,12 +423,7 @@ void tokenize(Buf *buf, Tokenization *out) {
switch (c) {
case WHITESPACE:
break;
case 'c':
t.state = TokenizeStateSymbolFirstC;
begin_token(&t, TokenIdSymbol);
buf_append_char(&t.cur_tok->data.str_lit.str, c);
break;
case ALPHA_EXCEPT_C:
case ALPHA:
case '_':
t.state = TokenizeStateSymbol;
begin_token(&t, TokenIdSymbol);
@ -1007,19 +996,7 @@ void tokenize(Buf *buf, Tokenization *out) {
switch (c) {
case WHITESPACE:
break;
case 'c':
if (!t.cur_tok->data.str_lit.is_c_str) {
t.pos -= 1;
end_token(&t);
t.state = TokenizeStateStart;
break;
}
t.state = TokenizeStateLineStringContinueC;
break;
case '\\':
if (t.cur_tok->data.str_lit.is_c_str) {
invalid_char_error(&t, c);
}
t.state = TokenizeStateLineStringContinue;
break;
default:
@ -1084,29 +1061,6 @@ void tokenize(Buf *buf, Tokenization *out) {
break;
}
break;
case TokenizeStateSymbolFirstC:
switch (c) {
case '"':
set_token_id(&t, t.cur_tok, TokenIdStringLiteral);
t.cur_tok->data.str_lit.is_c_str = true;
t.state = TokenizeStateString;
break;
case '\\':
set_token_id(&t, t.cur_tok, TokenIdStringLiteral);
t.cur_tok->data.str_lit.is_c_str = true;
t.state = TokenizeStateSawBackslash;
break;
case SYMBOL_CHAR:
t.state = TokenizeStateSymbol;
buf_append_char(&t.cur_tok->data.str_lit.str, c);
break;
default:
t.pos -= 1;
end_token(&t);
t.state = TokenizeStateStart;
continue;
}
break;
case TokenizeStateSawAtSign:
switch (c) {
case '"':
@ -1544,7 +1498,6 @@ void tokenize(Buf *buf, Tokenization *out) {
tokenize_error(&t, "unterminated character literal");
break;
case TokenizeStateSymbol:
case TokenizeStateSymbolFirstC:
case TokenizeStateZero:
case TokenizeStateNumber:
case TokenizeStateFloatFraction:

View File

@ -149,7 +149,6 @@ struct TokenIntLit {
struct TokenStrLit {
Buf str;
bool is_c_str;
};
struct TokenCharLit {

View File

@ -323,17 +323,9 @@ static AstNode *trans_create_node_bool(Context *c, bool value) {
return bool_node;
}
static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
static AstNode *trans_create_node_str_lit(Context *c, Buf *buf) {
AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
node->data.string_literal.buf = buf;
node->data.string_literal.c = true;
return node;
}
static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
node->data.string_literal.buf = buf;
node->data.string_literal.c = false;
return node;
}
@ -632,7 +624,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
// zig_type_node
AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("std")));
AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
@ -3391,7 +3383,7 @@ static AstNode *trans_string_literal(Context *c, ResultUsed result_used, TransSc
case ZigClangStringLiteral_StringKind_UTF8: {
size_t str_len;
const char *str_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &str_len);
AstNode *node = trans_create_node_str_lit_c(c, buf_create_from_mem(str_ptr, str_len));
AstNode *node = trans_create_node_str_lit(c, buf_create_from_mem(str_ptr, str_len));
return maybe_suppress_result(c, result_used, node);
}
case ZigClangStringLiteral_StringKind_UTF16:
@ -4890,7 +4882,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
return trans_create_node_unsigned(c, tok->data.char_lit);
case CTokIdStrLit:
*tok_i += 1;
return trans_create_node_str_lit_c(c, buf_create_from_buf(&tok->data.str_lit));
return trans_create_node_str_lit(c, buf_create_from_buf(&tok->data.str_lit));
case CTokIdMinus:
*tok_i += 1;
return parse_ctok_num_lit(c, ctok, tok_i, true);
@ -4937,7 +4929,7 @@ static AstNode *parse_ctok_primary_expr(Context *c, CTokenize *ctok, size_t *tok
// (dest)(x)
AstNode *import_builtin = trans_create_node_builtin_fn_call_str(c, "import");
import_builtin->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("builtin")));
import_builtin->data.fn_call_expr.params.append(trans_create_node_str_lit(c, buf_create_from_str("builtin")));
AstNode *typeid_type = trans_create_node_field_access_str(c, import_builtin, "TypeId");
AstNode *typeid_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");
AstNode *typeid_integer = trans_create_node_field_access_str(c, typeid_type, "Int");

View File

@ -7,7 +7,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
cases.addC("hello world with libc",
\\const c = @cImport(@cInclude("stdio.h"));
\\export fn main(argc: c_int, argv: [*][*]u8) c_int {
\\ _ = c.puts(c"Hello, world!");
\\ _ = c.puts("Hello, world!");
\\ return 0;
\\}
, "Hello, world!" ++ std.cstr.line_sep);
@ -144,75 +144,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ // we want actual \n, not \r\n
\\ _ = c._setmode(1, c._O_BINARY);
\\ }
\\ _ = c.printf(c"0: %llu\n",
\\ _ = c.printf("0: %llu\n",
\\ @as(u64, 0));
\\ _ = c.printf(c"320402575052271: %llu\n",
\\ _ = c.printf("320402575052271: %llu\n",
\\ @as(u64, 320402575052271));
\\ _ = c.printf(c"0x01236789abcdef: %llu\n",
\\ _ = c.printf("0x01236789abcdef: %llu\n",
\\ @as(u64, 0x01236789abcdef));
\\ _ = c.printf(c"0xffffffffffffffff: %llu\n",
\\ _ = c.printf("0xffffffffffffffff: %llu\n",
\\ @as(u64, 0xffffffffffffffff));
\\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n",
\\ _ = c.printf("0x000000ffffffffffffffff: %llu\n",
\\ @as(u64, 0x000000ffffffffffffffff));
\\ _ = c.printf(c"0o1777777777777777777777: %llu\n",
\\ _ = c.printf("0o1777777777777777777777: %llu\n",
\\ @as(u64, 0o1777777777777777777777));
\\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n",
\\ _ = c.printf("0o0000001777777777777777777777: %llu\n",
\\ @as(u64, 0o0000001777777777777777777777));
\\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ _ = c.printf("0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111));
\\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ _ = c.printf("0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111));
\\
\\ _ = c.printf(c"\n");
\\ _ = c.printf("\n");
\\
\\ _ = c.printf(c"0.0: %.013a\n",
\\ _ = c.printf("0.0: %.013a\n",
\\ @as(f64, 0.0));
\\ _ = c.printf(c"0e0: %.013a\n",
\\ _ = c.printf("0e0: %.013a\n",
\\ @as(f64, 0e0));
\\ _ = c.printf(c"0.0e0: %.013a\n",
\\ _ = c.printf("0.0e0: %.013a\n",
\\ @as(f64, 0.0e0));
\\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
\\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
\\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));
\\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
\\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
\\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));
\\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
\\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
\\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000));
\\ _ = c.printf(c"1.0: %.013a\n",
\\ _ = c.printf("1.0: %.013a\n",
\\ @as(f64, 1.0));
\\ _ = c.printf(c"10.0: %.013a\n",
\\ _ = c.printf("10.0: %.013a\n",
\\ @as(f64, 10.0));
\\ _ = c.printf(c"10.5: %.013a\n",
\\ _ = c.printf("10.5: %.013a\n",
\\ @as(f64, 10.5));
\\ _ = c.printf(c"10.5e5: %.013a\n",
\\ _ = c.printf("10.5e5: %.013a\n",
\\ @as(f64, 10.5e5));
\\ _ = c.printf(c"10.5e+5: %.013a\n",
\\ _ = c.printf("10.5e+5: %.013a\n",
\\ @as(f64, 10.5e+5));
\\ _ = c.printf(c"50.0e-2: %.013a\n",
\\ _ = c.printf("50.0e-2: %.013a\n",
\\ @as(f64, 50.0e-2));
\\ _ = c.printf(c"50e-2: %.013a\n",
\\ _ = c.printf("50e-2: %.013a\n",
\\ @as(f64, 50e-2));
\\
\\ _ = c.printf(c"\n");
\\ _ = c.printf("\n");
\\
\\ _ = c.printf(c"0x1.0: %.013a\n",
\\ _ = c.printf("0x1.0: %.013a\n",
\\ @as(f64, 0x1.0));
\\ _ = c.printf(c"0x10.0: %.013a\n",
\\ _ = c.printf("0x10.0: %.013a\n",
\\ @as(f64, 0x10.0));
\\ _ = c.printf(c"0x100.0: %.013a\n",
\\ _ = c.printf("0x100.0: %.013a\n",
\\ @as(f64, 0x100.0));
\\ _ = c.printf(c"0x103.0: %.013a\n",
\\ _ = c.printf("0x103.0: %.013a\n",
\\ @as(f64, 0x103.0));
\\ _ = c.printf(c"0x103.7: %.013a\n",
\\ _ = c.printf("0x103.7: %.013a\n",
\\ @as(f64, 0x103.7));
\\ _ = c.printf(c"0x103.70: %.013a\n",
\\ _ = c.printf("0x103.70: %.013a\n",
\\ @as(f64, 0x103.70));
\\ _ = c.printf(c"0x103.70p4: %.013a\n",
\\ _ = c.printf("0x103.70p4: %.013a\n",
\\ @as(f64, 0x103.70p4));
\\ _ = c.printf(c"0x103.70p5: %.013a\n",
\\ _ = c.printf("0x103.70p5: %.013a\n",
\\ @as(f64, 0x103.70p5));
\\ _ = c.printf(c"0x103.70p+5: %.013a\n",
\\ _ = c.printf("0x103.70p+5: %.013a\n",
\\ @as(f64, 0x103.70p+5));
\\ _ = c.printf(c"0x103.70p-5: %.013a\n",
\\ _ = c.printf("0x103.70p-5: %.013a\n",
\\ @as(f64, 0x103.70p-5));
\\
\\ return 0;
@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ const x: f64 = small;
\\ const y = @floatToInt(i32, x);
\\ const z = @intToFloat(f64, y);
\\ _ = c.printf(c"%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4));
\\ _ = c.printf("%.2f\n%d\n%.2f\n%.2f\n", x, y, z, @as(f64, -0.4));
\\ return 0;
\\}
, "3.25\n3\n3.00\n-0.40\n");

View File

@ -164,7 +164,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"using an unknown len ptr type instead of array",
\\const resolutions = [*][*]const u8{
\\ c"[320 240 ]",
\\ "[320 240 ]",
\\ null,
\\};
\\comptime {
@ -781,7 +781,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"peer cast then implicit cast const pointer to mutable C pointer",
\\export fn func() void {
\\ var strValue: [*c]u8 = undefined;
\\ strValue = strValue orelse c"";
\\ strValue = strValue orelse "";
\\}
,
"tmp.zig:3:32: error: cast discards const qualifier",
@ -1115,7 +1115,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
"libc headers note",
\\const c = @cImport(@cInclude("stdio.h"));
\\export fn entry() void {
\\ _ = c.printf(c"hello, world!\n");
\\ _ = c.printf("hello, world!\n");
\\}
,
"tmp.zig:1:11: error: C import failed",
@ -3352,7 +3352,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"variable has wrong type",
\\export fn f() i32 {
\\ const a = c"a";
\\ const a = "a";
\\ return a;
\\}
,
@ -4786,7 +4786,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.add(
"assign through constant pointer",
\\export fn f() void {
\\ var cstr = c"Hat";
\\ var cstr = "Hat";
\\ cstr[0] = 'W';
\\}
,

View File

@ -132,9 +132,16 @@ test "single-item pointer to array indexing and slicing" {
}
fn testSingleItemPtrArrayIndexSlice() void {
var array = "aaaa";
doSomeMangling(&array);
expect(mem.eql(u8, "azya", array));
{
var array: [4]u8 = "aaaa".*;
doSomeMangling(&array);
expect(mem.eql(u8, "azya", &array));
}
{
var array = "aaaa".*;
doSomeMangling(&array);
expect(mem.eql(u8, "azya", &array));
}
}
fn doSomeMangling(array: *[4]u8) void {
@ -294,9 +301,16 @@ test "read/write through global variable array of struct fields initialized via
}
test "implicit cast zero sized array ptr to slice" {
var b = "";
const c: []const u8 = &b;
expect(c.len == 0);
{
var b = "".*;
const c: []const u8 = &b;
expect(c.len == 0);
}
{
var b: [0]u8 = "".*;
const c: []const u8 = &b;
expect(c.len == 0);
}
}
test "anonymous list literal syntax" {
@ -333,3 +347,16 @@ test "anonymous literal in array" {
S.doTheTest();
comptime S.doTheTest();
}
test "access the null element of a null terminated array" {
const S = struct {
fn doTheTest() void {
var array: [4]null u8 = .{'a', 'o', 'e', 'u'};
comptime expect(array[4] == 0);
var len: usize = 4;
expect(array[len] == 0);
}
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -8,8 +8,16 @@ test "comptime code should not modify constant data" {
}
fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu";
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
{
var array = "aoeu".*;
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
}
{
var array: [4]u8 = "aoeu".*;
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
}
}

View File

@ -179,18 +179,24 @@ fn gimmeErrOrSlice() anyerror![]u8 {
}
test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
{
var data = "hi";
const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
comptime {
var data = "hi";
const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
const S = struct {
fn doTheTest() anyerror!void {
{
var data = "hi".*;
const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
{
var data: [2]u8 = "hi".*;
const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
}
}
};
try S.doTheTest();
try comptime S.doTheTest();
}
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
if (a) {
@ -217,11 +223,20 @@ test "implicit cast from &const [N]T to []const T" {
}
fn testCastConstArrayRefToConstSlice() void {
const blah = "aoeu";
const const_array_ref = &blah;
expect(@typeOf(const_array_ref) == *const [4]u8);
const slice: []const u8 = const_array_ref;
expect(mem.eql(u8, slice, "aoeu"));
{
const blah = "aoeu".*;
const const_array_ref = &blah;
expect(@typeOf(const_array_ref) == *const [4]null u8);
const slice: []const u8 = const_array_ref;
expect(mem.eql(u8, slice, "aoeu"));
}
{
const blah: [4]u8 = "aoeu".*;
const const_array_ref = &blah;
expect(@typeOf(const_array_ref) == *const [4]u8);
const slice: []const u8 = const_array_ref;
expect(mem.eql(u8, slice, "aoeu"));
}
}
test "peer type resolution: error and [N]T" {
@ -310,17 +325,28 @@ test "single-item pointer of array to slice and to unknown length pointer" {
}
fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu";
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
const y: []u8 = &array;
y[0] += 1;
expect(mem.eql(u8, array[0..], "coeu"));
{
var array = "aoeu".*;
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
const y: []u8 = &array;
y[0] += 1;
expect(mem.eql(u8, array[0..], "coeu"));
}
{
var array: [4]u8 = "aoeu".*;
const x: [*]u8 = &array;
x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu"));
const y: []u8 = &array;
y[0] += 1;
expect(mem.eql(u8, array[0..], "coeu"));
}
}
test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
const window_name = [1][*]const u8{c"window name"};
const window_name = [1][*]const u8{"window name"};
const x: [*]const ?[*]const u8 = &window_name;
expect(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
}
@ -545,7 +571,7 @@ test "implicit cast *[0]T to E![]const u8" {
}
test "peer cast *[0]T to E![]const T" {
var buffer: [5]u8 = "abcde";
var buffer: [5]u8 = "abcde".*;
var buf: anyerror![]const u8 = buffer[0..];
var b = false;
var y = if (b) &[0]u8{} else buf;
@ -553,7 +579,7 @@ test "peer cast *[0]T to E![]const T" {
}
test "peer cast *[0]T to []const T" {
var buffer: [5]u8 = "abcde";
var buffer: [5]u8 = "abcde".*;
var buf: []const u8 = buffer[0..];
var b = false;
var y = if (b) &[0]u8{} else buf;
@ -565,3 +591,33 @@ test "cast from array reference to fn" {
const f = @ptrCast(extern fn () void, &global_array);
expect(@ptrToInt(f) == @ptrToInt(&global_array));
}
test "*const [N]null u8 to ?[]const u8" {
const S = struct {
fn doTheTest() void {
var a = "Hello";
var b: ?[]const u8 = a;
expect(mem.eql(u8, b.?, "Hello"));
}
};
S.doTheTest();
comptime S.doTheTest();
}
test "peer resolution of string literals" {
const S = struct {
const E = extern enum { a, b, c, d};
fn doTheTest(e: E) void {
const cmd = switch (e) {
.a => "one",
.b => "two",
.c => "three",
.d => "four",
};
expect(mem.eql(u8, cmd, "two"));
}
};
S.doTheTest(.b);
comptime S.doTheTest(.b);
}

View File

@ -6,12 +6,11 @@ var argv: [*]const [*]const u8 = undefined;
test "const slice child" {
const strs = [_][*]const u8{
c"one",
c"two",
c"three",
"one",
"two",
"three",
};
// TODO this should implicitly cast
argv = @ptrCast([*]const [*]const u8, &strs);
argv = &strs;
bar(strs.len);
}

View File

@ -736,7 +736,7 @@ test "comptime pointer cast array and then slice" {
test "slice bounds in comptime concatenation" {
const bs = comptime blk: {
const b = c"........1........";
const b = "........1........";
break :blk b[8..9];
};
const str = "" ++ bs;

View File

@ -204,11 +204,11 @@ test "multiline string" {
test "multiline C string" {
const s1 =
c\\one
c\\two)
c\\three
\\one
\\two)
\\three
;
const s2 = c"one\ntwo)\nthree";
const s2 = "one\ntwo)\nthree";
expect(std.cstr.cmp(s1, s2) == 0);
}
@ -358,9 +358,12 @@ fn ptrEql(a: *const []const u8, b: *const []const u8) bool {
return a == b;
}
test "C string concatenation" {
const a = c"OK" ++ c" IT " ++ c"WORKED";
const b = c"OK IT WORKED";
test "string concatenation" {
const a = "OK" ++ " IT " ++ "WORKED";
const b = "OK IT WORKED";
comptime expect(@typeOf(a) == *const [12]null u8);
comptime expect(@typeOf(b) == *const [12]null u8);
const len = mem.len(u8, b);
const len_with_null = len + 1;

View File

@ -15,7 +15,7 @@ fn testDerefPtr() void {
}
test "pointer arithmetic" {
var ptr = c"abcd";
var ptr: [*]const u8 = "abcd";
expect(ptr[0] == 'a');
ptr += 1;

View File

@ -60,7 +60,7 @@ test "comptime ptrcast keeps larger alignment" {
}
test "implicit optional pointer to optional c_void pointer" {
var buf: [4]u8 = "aoeu";
var buf: [4]u8 = "aoeu".*;
var x: ?[*]u8 = &buf;
var y: ?*c_void = x;
var z = @ptrCast(*[4]u8, y);

View File

@ -36,7 +36,7 @@ fn assertLenIsZero(msg: []const u8) void {
}
test "C pointer" {
var buf: [*c]const u8 = c"kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
var len: u32 = 10;
var slice = buf[0..len];
expectEqualSlices(u8, "kjdhfkjdhf", slice);

View File

@ -493,7 +493,7 @@ test "non-byte-aligned array inside packed struct" {
fn doTheTest() void {
var foo = Foo{
.a = true,
.b = "abcdefghijklmnopqurstu",
.b = "abcdefghijklmnopqurstu".*,
};
bar(foo.b);
}

View File

@ -6,7 +6,7 @@ pub fn addCases(ctx: *TestContext) !void {
try ctx.testCompareOutputLibC(
\\extern fn puts([*]const u8) void;
\\export fn main() c_int {
\\ puts(c"Hello, world!");
\\ puts("Hello, world!");
\\ return 0;
\\}
, "Hello, world!" ++ std.cstr.line_sep);
@ -15,7 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
try ctx.testCompareOutputLibC(
\\extern fn puts(s: [*]const u8) void;
\\export fn main() c_int {
\\ return foo(c"OK");
\\ return foo("OK");
\\}
\\fn foo(s: [*]const u8) c_int {
\\ puts(s);

View File

@ -5,7 +5,7 @@ const c = @cImport({
@cInclude("string.h");
});
const msg = c"Hello, world!\n";
const msg = "Hello, world!\n";
export fn main(argc: c_int, argv: **u8) c_int {
if (c.printf(msg) != @intCast(c_int, c.strlen(msg))) return -1;

View File

@ -47,7 +47,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo() void {
\\ var a: c_int = undefined;
\\ _ = 1;
\\ _ = c"hey";
\\ _ = "hey";
\\ _ = (1 + 1);
\\ _ = (1 - 1);
\\ a = 1;
@ -213,9 +213,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\pub fn foo() void {
\\ _ = c"foo";
\\ _ = c"foo";
\\ _ = c"void foo(void)";
\\ _ = "foo";
\\ _ = "foo";
\\ _ = "void foo(void)";
\\}
);
@ -232,7 +232,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo() void {
\\ var a: c_int = undefined;
\\ _ = 1;
\\ _ = c"hey";
\\ _ = "hey";
\\ _ = (1 + 1);
\\ _ = (1 - 1);
\\ a = 1;
@ -543,7 +543,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("#define string",
\\#define foo "a string"
,
\\pub const foo = c"a string";
\\pub const foo = "a string";
);
cases.add("__cdecl doesn't mess up function pointers",
@ -617,9 +617,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO2 "aoeu\x0007a derp"
\\#define FOO_CHAR '\xfF'
,
\\pub const FOO = c"aoeu\xab derp";
\\pub const FOO = "aoeu\xab derp";
,
\\pub const FOO2 = c"aoeuz derp";
\\pub const FOO2 = "aoeuz derp";
,
\\pub const FOO_CHAR = 255;
);
@ -629,9 +629,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO2 "aoeu\0234 derp"
\\#define FOO_CHAR '\077'
,
\\pub const FOO = c"aoeu\x13 derp";
\\pub const FOO = "aoeu\x13 derp";
,
\\pub const FOO2 = c"aoeu\x134 derp";
\\pub const FOO2 = "aoeu\x134 derp";
,
\\pub const FOO_CHAR = 63;
);
@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\pub fn foo() [*c]const u8 {
\\ return c"bar";
\\ return "bar";
\\}
);
@ -1523,7 +1523,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("const ptr initializer",
\\static const char *v0 = "0.0.0";
,
\\pub var v0: [*c]const u8 = c"0.0.0";
\\pub var v0: [*c]const u8 = "0.0.0";
);
cases.add("static incomplete array inside function",
@ -1532,7 +1532,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\}
,
\\pub fn foo() void {
\\ const v2: [*c]const u8 = c"2.2.2";
\\ const v2: [*c]const u8 = "2.2.2";
\\}
);
@ -1809,7 +1809,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\ var i: u8 = @as(u8, '\x0b');
\\ var j: u8 = @as(u8, '\x00');
\\ var k: u8 = @as(u8, '\"');
\\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
\\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
\\}
\\
);