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.
This commit is contained in:
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 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) 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.PathAlreadyExists => unreachable,
error.NoSpaceLeft => unreachable, error.NoSpaceLeft => unreachable,
error.FileTooBig => unreachable, error.FileTooBig => unreachable,

View File

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

View File

@ -27,8 +27,8 @@ test "cstr fns" {
} }
fn testCStrFnsImpl() void { fn testCStrFnsImpl() void {
testing.expect(cmp(c"aoeu", c"aoez") == -1); testing.expect(cmp("aoeu", "aoez") == -1);
testing.expect(mem.len(u8, c"123456789") == 9); testing.expect(mem.len(u8, "123456789") == 9);
} }
/// Returns a mutable slice with 1 more byte of length which is a null byte. /// 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 std = @import("std.zig");
const math = std.math; const math = std.math;
const debug = std.debug; const assert = std.debug.assert;
const assert = debug.assert;
const testing = std.testing;
const mem = std.mem; const mem = std.mem;
const builtin = @import("builtin"); const builtin = @import("builtin");
const errol = @import("fmt/errol.zig"); 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 { fn peekIsAlign(comptime fmt: []const u8) bool {
// Should only be called during a state transition to the format segment. // 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| { inline for (([_]u8{ 1, 2 })[0..]) |i| {
if (fmt.len > i and (fmt[i] == '<' or fmt[i] == '^' or fmt[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" { test "parseInt" {
testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10); std.testing.expect((parseInt(i32, "-10", 10) catch unreachable) == -10);
testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10); std.testing.expect((parseInt(i32, "+10", 10) catch unreachable) == 10);
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);
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);
testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter); std.testing.expect(if (parseInt(u32, "-10", 10)) |_| false else |err| err == error.InvalidCharacter);
testing.expect((parseInt(u8, "255", 10) catch unreachable) == 255); std.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(if (parseInt(u8, "256", 10)) |_| false else |err| err == error.Overflow);
} }
const ParseUnsignedError = error{ const ParseUnsignedError = error{
@ -1040,30 +1038,30 @@ pub fn parseUnsigned(comptime T: type, buf: []const u8, radix: u8) ParseUnsigned
} }
test "parseUnsigned" { test "parseUnsigned" {
testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124); std.testing.expect((try parseUnsigned(u16, "050124", 10)) == 50124);
testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535); std.testing.expect((try parseUnsigned(u16, "65535", 10)) == 65535);
testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10)); std.testing.expectError(error.Overflow, parseUnsigned(u16, "65536", 10));
testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff); std.testing.expect((try parseUnsigned(u64, "0ffffffffffffffff", 16)) == 0xffffffffffffffff);
testing.expectError(error.Overflow, parseUnsigned(u64, "10000000000000000", 16)); 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); std.testing.expect((try parseUnsigned(u7, "1", 10)) == 1);
testing.expect((try parseUnsigned(u7, "1000", 2)) == 8); std.testing.expect((try parseUnsigned(u7, "1000", 2)) == 8);
testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10)); std.testing.expectError(error.InvalidCharacter, parseUnsigned(u32, "f", 10));
testing.expectError(error.InvalidCharacter, parseUnsigned(u8, "109", 8)); 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 // these numbers should fit even though the radix itself doesn't fit in the destination type
testing.expect((try parseUnsigned(u1, "0", 10)) == 0); std.testing.expect((try parseUnsigned(u1, "0", 10)) == 0);
testing.expect((try parseUnsigned(u1, "1", 10)) == 1); std.testing.expect((try parseUnsigned(u1, "1", 10)) == 1);
testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10)); std.testing.expectError(error.Overflow, parseUnsigned(u1, "2", 10));
testing.expect((try parseUnsigned(u1, "001", 16)) == 1); std.testing.expect((try parseUnsigned(u1, "001", 16)) == 1);
testing.expect((try parseUnsigned(u2, "3", 16)) == 3); std.testing.expect((try parseUnsigned(u2, "3", 16)) == 3);
testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16)); std.testing.expectError(error.Overflow, parseUnsigned(u2, "4", 16));
} }
pub const parseFloat = @import("fmt/parse_float.zig").parseFloat; pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
@ -1134,19 +1132,19 @@ fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
test "bufPrintInt" { test "bufPrintInt" {
var buffer: [100]u8 = undefined; var buffer: [100]u8 = undefined;
const buf = buffer[0..]; const buf = buffer[0..];
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), 2, false, FormatOptions{}), "-101111000110000101001110"));
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), 10, false, FormatOptions{}), "-12345678"));
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, 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), 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")); std.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")); std.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, 0x1234), 16, false, FormatOptions{ .width = 1 }), "1234"));
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"));
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 { 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" { test "parse unsigned comptime" {
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..] }; var context = BufPrintContext{ .remaining = buf1[0..] };
try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
var res = buf1[0 .. buf1.len - context.remaining.len]; 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..] }; context = BufPrintContext{ .remaining = buf1[0..] };
try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len]; 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..] }; context = BufPrintContext{ .remaining = buf1[0..] };
try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
res = buf1[0 .. buf1.len - context.remaining.len]; 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" { 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);
try testFmt("array: abc\n", "array: {}\n", &value); try testFmt("array: abc\n", "array: {}\n", &value);
@ -1278,8 +1276,8 @@ test "pointer" {
} }
test "cstr" { test "cstr" {
try testFmt("cstr: Test C\n", "cstr: {s}\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", c"Test C"); try testFmt("cstr: Test C \n", "cstr: {s:10}\n", "Test C");
} }
test "filesize" { test "filesize" {
@ -1479,10 +1477,10 @@ test "union" {
var buf: [100]u8 = undefined; var buf: [100]u8 = undefined;
const uu_result = try bufPrint(buf[0..], "{}", uu_inst); 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); 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" { test "enum" {
@ -1569,11 +1567,11 @@ pub fn trim(buf: []const u8) []const u8 {
} }
test "trim" { test "trim" {
testing.expect(mem.eql(u8, "abc", trim("\n abc \t"))); std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
testing.expect(mem.eql(u8, "", trim(" "))); std.testing.expect(mem.eql(u8, "", trim(" ")));
testing.expect(mem.eql(u8, "", trim(""))); std.testing.expect(mem.eql(u8, "", trim("")));
testing.expect(mem.eql(u8, "abc", trim(" abc"))); std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
testing.expect(mem.eql(u8, "abc", trim("abc "))); std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
} }
pub fn isWhiteSpace(byte: u8) bool { 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, ""); var buf = try std.Buffer.init(std.debug.global_allocator, "");
try formatIntValue(value, "", FormatOptions{}, &buf, @typeOf(std.Buffer.append).ReturnType.ErrorSet, std.Buffer.append); 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" { test "formatType max_depth" {
@ -1661,19 +1659,19 @@ test "formatType max_depth" {
var buf0 = try std.Buffer.init(std.debug.global_allocator, ""); 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); 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, ""); 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); 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, ""); 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); 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, ""); 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); 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" { test "positional" {

View File

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

View File

@ -172,7 +172,7 @@ pub const File = struct {
if (self.isTty()) { if (self.isTty()) {
if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) { if (self.handle == os.STDOUT_FILENO or self.handle == os.STDERR_FILENO) {
// Use getenvC to workaround https://github.com/ziglang/zig/issues/3511 // 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")) if (std.mem.eql(u8, term, "dumb"))
return false; 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 // 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 result_disk_designator: []const u8 = "";
var have_drive_kind = WindowsPath.Kind.None; var have_drive_kind = WindowsPath.Kind.None;
var have_abs_path = false; 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" { test "siphash64-2-4 sanity" {
const vectors = [_][8]u8{ const vectors = [_][8]u8{
"\x31\x0e\x0e\xdd\x47\xdb\x6f\x72", // "" "\x31\x0e\x0e\xdd\x47\xdb\x6f\x72".*, // ""
"\xfd\x67\xdc\x93\xc5\x39\xf8\x74", // "\x00" "\xfd\x67\xdc\x93\xc5\x39\xf8\x74".*, // "\x00"
"\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d", // "\x00\x01" ... etc "\x5a\x4f\xa9\xd9\x09\x80\x6c\x0d".*, // "\x00\x01" ... etc
"\x2d\x7e\xfb\xd7\x96\x66\x67\x85", "\x2d\x7e\xfb\xd7\x96\x66\x67\x85".*,
"\xb7\x87\x71\x27\xe0\x94\x27\xcf", "\xb7\x87\x71\x27\xe0\x94\x27\xcf".*,
"\x8d\xa6\x99\xcd\x64\x55\x76\x18", "\x8d\xa6\x99\xcd\x64\x55\x76\x18".*,
"\xce\xe3\xfe\x58\x6e\x46\xc9\xcb", "\xce\xe3\xfe\x58\x6e\x46\xc9\xcb".*,
"\x37\xd1\x01\x8b\xf5\x00\x02\xab", "\x37\xd1\x01\x8b\xf5\x00\x02\xab".*,
"\x62\x24\x93\x9a\x79\xf5\xf5\x93", "\x62\x24\x93\x9a\x79\xf5\xf5\x93".*,
"\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e", "\xb0\xe4\xa9\x0b\xdf\x82\x00\x9e".*,
"\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a", "\xf3\xb9\xdd\x94\xc5\xbb\x5d\x7a".*,
"\xa7\xad\x6b\x22\x46\x2f\xb3\xf4", "\xa7\xad\x6b\x22\x46\x2f\xb3\xf4".*,
"\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75", "\xfb\xe5\x0e\x86\xbc\x8f\x1e\x75".*,
"\x90\x3d\x84\xc0\x27\x56\xea\x14", "\x90\x3d\x84\xc0\x27\x56\xea\x14".*,
"\xee\xf2\x7a\x8e\x90\xca\x23\xf7", "\xee\xf2\x7a\x8e\x90\xca\x23\xf7".*,
"\xe5\x45\xbe\x49\x61\xca\x29\xa1", "\xe5\x45\xbe\x49\x61\xca\x29\xa1".*,
"\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f", "\xdb\x9b\xc2\x57\x7f\xcc\x2a\x3f".*,
"\x94\x47\xbe\x2c\xf5\xe9\x9a\x69", "\x94\x47\xbe\x2c\xf5\xe9\x9a\x69".*,
"\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b", "\x9c\xd3\x8d\x96\xf0\xb3\xc1\x4b".*,
"\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb", "\xbd\x61\x79\xa7\x1d\xc9\x6d\xbb".*,
"\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe", "\x98\xee\xa2\x1a\xf2\x5c\xd6\xbe".*,
"\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0", "\xc7\x67\x3b\x2e\xb0\xcb\xf2\xd0".*,
"\x88\x3e\xa3\xe3\x95\x67\x53\x93", "\x88\x3e\xa3\xe3\x95\x67\x53\x93".*,
"\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8", "\xc8\xce\x5c\xcd\x8c\x03\x0c\xa8".*,
"\x94\xaf\x49\xf6\xc6\x50\xad\xb8", "\x94\xaf\x49\xf6\xc6\x50\xad\xb8".*,
"\xea\xb8\x85\x8a\xde\x92\xe1\xbc", "\xea\xb8\x85\x8a\xde\x92\xe1\xbc".*,
"\xf3\x15\xbb\x5b\xb8\x35\xd8\x17", "\xf3\x15\xbb\x5b\xb8\x35\xd8\x17".*,
"\xad\xcf\x6b\x07\x63\x61\x2e\x2f", "\xad\xcf\x6b\x07\x63\x61\x2e\x2f".*,
"\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde", "\xa5\xc9\x1d\xa7\xac\xaa\x4d\xde".*,
"\x71\x65\x95\x87\x66\x50\xa2\xa6", "\x71\x65\x95\x87\x66\x50\xa2\xa6".*,
"\x28\xef\x49\x5c\x53\xa3\x87\xad", "\x28\xef\x49\x5c\x53\xa3\x87\xad".*,
"\x42\xc3\x41\xd8\xfa\x92\xd8\x32", "\x42\xc3\x41\xd8\xfa\x92\xd8\x32".*,
"\xce\x7c\xf2\x72\x2f\x51\x27\x71", "\xce\x7c\xf2\x72\x2f\x51\x27\x71".*,
"\xe3\x78\x59\xf9\x46\x23\xf3\xa7", "\xe3\x78\x59\xf9\x46\x23\xf3\xa7".*,
"\x38\x12\x05\xbb\x1a\xb0\xe0\x12", "\x38\x12\x05\xbb\x1a\xb0\xe0\x12".*,
"\xae\x97\xa1\x0f\xd4\x34\xe0\x15", "\xae\x97\xa1\x0f\xd4\x34\xe0\x15".*,
"\xb4\xa3\x15\x08\xbe\xff\x4d\x31", "\xb4\xa3\x15\x08\xbe\xff\x4d\x31".*,
"\x81\x39\x62\x29\xf0\x90\x79\x02", "\x81\x39\x62\x29\xf0\x90\x79\x02".*,
"\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca", "\x4d\x0c\xf4\x9e\xe5\xd4\xdc\xca".*,
"\x5c\x73\x33\x6a\x76\xd8\xbf\x9a", "\x5c\x73\x33\x6a\x76\xd8\xbf\x9a".*,
"\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e", "\xd0\xa7\x04\x53\x6b\xa9\x3e\x0e".*,
"\x92\x59\x58\xfc\xd6\x42\x0c\xad", "\x92\x59\x58\xfc\xd6\x42\x0c\xad".*,
"\xa9\x15\xc2\x9b\xc8\x06\x73\x18", "\xa9\x15\xc2\x9b\xc8\x06\x73\x18".*,
"\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4", "\x95\x2b\x79\xf3\xbc\x0a\xa6\xd4".*,
"\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9", "\xf2\x1d\xf2\xe4\x1d\x45\x35\xf9".*,
"\x87\x57\x75\x19\x04\x8f\x53\xa9", "\x87\x57\x75\x19\x04\x8f\x53\xa9".*,
"\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb", "\x10\xa5\x6c\xf5\xdf\xcd\x9a\xdb".*,
"\xeb\x75\x09\x5c\xcd\x98\x6c\xd0", "\xeb\x75\x09\x5c\xcd\x98\x6c\xd0".*,
"\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6", "\x51\xa9\xcb\x9e\xcb\xa3\x12\xe6".*,
"\x96\xaf\xad\xfc\x2c\xe6\x66\xc7", "\x96\xaf\xad\xfc\x2c\xe6\x66\xc7".*,
"\x72\xfe\x52\x97\x5a\x43\x64\xee", "\x72\xfe\x52\x97\x5a\x43\x64\xee".*,
"\x5a\x16\x45\xb2\x76\xd5\x92\xa1", "\x5a\x16\x45\xb2\x76\xd5\x92\xa1".*,
"\xb2\x74\xcb\x8e\xbf\x87\x87\x0a", "\xb2\x74\xcb\x8e\xbf\x87\x87\x0a".*,
"\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81", "\x6f\x9b\xb4\x20\x3d\xe7\xb3\x81".*,
"\xea\xec\xb2\xa3\x0b\x22\xa8\x7f", "\xea\xec\xb2\xa3\x0b\x22\xa8\x7f".*,
"\x99\x24\xa4\x3c\xc1\x31\x57\x24", "\x99\x24\xa4\x3c\xc1\x31\x57\x24".*,
"\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7", "\xbd\x83\x8d\x3a\xaf\xbf\x8d\xb7".*,
"\x0b\x1a\x2a\x32\x65\xd5\x1a\xea", "\x0b\x1a\x2a\x32\x65\xd5\x1a\xea".*,
"\x13\x50\x79\xa3\x23\x1c\xe6\x60", "\x13\x50\x79\xa3\x23\x1c\xe6\x60".*,
"\x93\x2b\x28\x46\xe4\xd7\x06\x66", "\x93\x2b\x28\x46\xe4\xd7\x06\x66".*,
"\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c", "\xe1\x91\x5f\x5c\xb1\xec\xa4\x6c".*,
"\xf3\x25\x96\x5c\xa1\x6d\x62\x9f", "\xf3\x25\x96\x5c\xa1\x6d\x62\x9f".*,
"\x57\x5f\xf2\x8e\x60\x38\x1b\xe5", "\x57\x5f\xf2\x8e\x60\x38\x1b\xe5".*,
"\x72\x45\x06\xeb\x4c\x32\x8a\x95", "\x72\x45\x06\xeb\x4c\x32\x8a\x95".*,
}; };
const siphash = SipHash64(2, 4); const siphash = SipHash64(2, 4);
@ -281,70 +281,70 @@ test "siphash64-2-4 sanity" {
test "siphash128-2-4 sanity" { test "siphash128-2-4 sanity" {
const vectors = [_][16]u8{ const vectors = [_][16]u8{
"\xa3\x81\x7f\x04\xba\x25\xa8\xe6\x6d\xf6\x72\x14\xc7\x55\x02\x93", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\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", "\x51\x50\xd1\x77\x2f\x50\x83\x4a\x50\x3e\x06\x9a\x97\x3f\xbd\x7c".*,
}; };
const siphash = SipHash128(2, 4); const siphash = SipHash128(2, 4);

View File

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

View File

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

View File

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

View File

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

View File

@ -666,35 +666,35 @@ const Policy = struct {
const defined_policies = [_]Policy{ const defined_policies = [_]Policy{
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, .len = 15,
.mask = 0xff, .mask = 0xff,
.prec = 50, .prec = 50,
.label = 0, .label = 0,
}, },
Policy{ 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, .len = 11,
.mask = 0xff, .mask = 0xff,
.prec = 35, .prec = 35,
.label = 4, .label = 4,
}, },
Policy{ 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, .len = 1,
.mask = 0xff, .mask = 0xff,
.prec = 30, .prec = 30,
.label = 2, .label = 2,
}, },
Policy{ 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, .len = 3,
.mask = 0xff, .mask = 0xff,
.prec = 5, .prec = 5,
.label = 5, .label = 5,
}, },
Policy{ 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, .len = 0,
.mask = 0xfe, .mask = 0xfe,
.prec = 3, .prec = 3,
@ -708,7 +708,7 @@ const defined_policies = [_]Policy{
// { "\x3f\xfe", 1, 0xff, 1, 12 }, // { "\x3f\xfe", 1, 0xff, 1, 12 },
// Last rule must match all addresses to stop loop. // Last rule must match all addresses to stop loop.
Policy{ 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, .len = 0,
.mask = 0, .mask = 0,
.prec = 40, .prec = 40,
@ -812,7 +812,7 @@ fn linuxLookupNameFromHosts(
family: os.sa_family_t, family: os.sa_family_t,
port: u16, port: u16,
) !void { ) !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.FileNotFound,
error.NotDir, error.NotDir,
error.AccessDenied, error.AccessDenied,
@ -1006,7 +1006,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
}; };
errdefer rc.deinit(); 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.FileNotFound,
error.NotDir, error.NotDir,
error.AccessDenied, error.AccessDenied,

View File

@ -157,7 +157,7 @@ pub fn getrandom(buffer: []u8) GetRandomError!void {
} }
fn getRandomBytesDevURandom(buf: []u8) !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); defer close(fd);
const st = try fstat(fd); const st = try fstat(fd);
@ -2674,7 +2674,7 @@ pub fn dl_iterate_phdr(
if (it.end()) { if (it.end()) {
var info = dl_phdr_info{ var info = dl_phdr_info{
.dlpi_addr = elf_base, .dlpi_addr = elf_base,
.dlpi_name = c"/proc/self/exe", .dlpi_name = "/proc/self/exe",
.dlpi_phdr = phdrs.ptr, .dlpi_phdr = phdrs.ptr,
.dlpi_phnum = ehdr.e_phnum, .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()) { if (it.end()) {
var info = dl_phdr_info{ var info = dl_phdr_info{
.dlpi_addr = elf_base, .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_phdr = @intToPtr([*]elf.Phdr, elf_base + __ehdr_start.e_phoff),
.dlpi_phnum = __ehdr_start.e_phnum, .dlpi_phnum = __ehdr_start.e_phnum,
}; };

View File

@ -56,7 +56,7 @@ test "statx" {
} }
var statx_buf: linux.Statx = undefined; 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 => {}, 0 => {},
// The statx syscall was only introduced in linux 4.11 // The statx syscall was only introduced in linux 4.11
linux.ENOSYS => return error.SkipZigTest, linux.ENOSYS => return error.SkipZigTest,
@ -64,7 +64,7 @@ test "statx" {
} }
var stat_buf: linux.Stat = undefined; 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 => {}, 0 => {},
else => unreachable, else => unreachable,
} }

View File

@ -473,14 +473,14 @@ pub fn argsFree(allocator: *mem.Allocator, args_alloc: []const []u8) void {
} }
test "windows arg parsing" { test "windows arg parsing" {
testWindowsCmdLine(c"a b\tc d", [_][]const u8{ "a", "b", "c", "d" }); testWindowsCmdLine("a b\tc d", [_][]const u8{ "a", "b", "c", "d" });
testWindowsCmdLine(c"\"abc\" d e", [_][]const u8{ "abc", "d", "e" }); testWindowsCmdLine("\"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("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("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("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 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", ".\\..\\zig-cache\\build",
"bin\\zig.exe", "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 { extern fn strerror(errnum: c_int) [*]const u8 {
return c"TODO strerror implementation"; return "TODO strerror implementation";
} }
test "strncmp" { test "strncmp" {
std.testing.expect(strncmp(c"a", c"b", 1) == -1); std.testing.expect(strncmp("a", "b", 1) == -1);
std.testing.expect(strncmp(c"a", c"c", 1) == -2); std.testing.expect(strncmp("a", "c", 1) == -2);
std.testing.expect(strncmp(c"b", c"a", 1) == 1); std.testing.expect(strncmp("b", "a", 1) == 1);
std.testing.expect(strncmp(c"\xff", c"\x02", 1) == 253); std.testing.expect(strncmp("\xff", "\x02", 1) == 253);
} }
// Avoid dragging in the runtime safety mechanisms into this .o file, // 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: c_int = undefined;
var count_len: usize = @sizeOf(c_int); 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) { os.sysctlbynameC(name, &count, &count_len, null, 0) catch |err| switch (err) {
error.NameTooLong => unreachable, error.NameTooLong => unreachable,
else => |e| return e, else => |e| return e,

View File

@ -3,7 +3,7 @@ const testing = std.testing;
const valgrind = std.valgrind; const valgrind = std.valgrind;
pub const MemCheckClientRequest = extern enum { pub const MemCheckClientRequest = extern enum {
MakeMemNoAccess = valgrind.ToolBase("MC"), MakeMemNoAccess = valgrind.ToolBase("MC".*),
MakeMemUndefined, MakeMemUndefined,
MakeMemDefined, MakeMemDefined,
Discard, 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_MINOR),
u32(c.ZIG_VERSION_PATCH), u32(c.ZIG_VERSION_PATCH),
); );
const flags = c""; const flags = "";
const runtime_version = 0; const runtime_version = 0;
const compile_unit_file = llvm.CreateFile( const compile_unit_file = llvm.CreateFile(
dibuilder, dibuilder,
@ -68,7 +68,7 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
is_optimized, is_optimized,
flags, flags,
runtime_version, runtime_version,
c"", "",
0, 0,
!comp.strip, !comp.strip,
) orelse return error.OutOfMemory; ) orelse return error.OutOfMemory;
@ -402,7 +402,7 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Poin
if (child_type.handleIsPtr()) { if (child_type.handleIsPtr()) {
return ptr; return ptr;
} }
return try renderLoad(ofile, ptr, ptr_type, c""); return try renderLoad(ofile, ptr, ptr_type, "");
} }
pub fn renderStoreUntyped( pub fn renderStoreUntyped(

View File

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

View File

@ -331,7 +331,7 @@ pub const Inst = struct {
@intCast(c_uint, args.len), @intCast(c_uint, args.len),
llvm_cc, llvm_cc,
fn_inline, fn_inline,
c"", "",
) orelse error.OutOfMemory; ) orelse error.OutOfMemory;
} }
}; };
@ -1410,7 +1410,7 @@ pub const Builder = struct {
if (block.label) |label| { if (block.label) |label| {
block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena()); block_scope.incoming_values = std.ArrayList(*Inst).init(irb.arena());
block_scope.incoming_blocks = std.ArrayList(*BasicBlock).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( block_scope.is_comptime = try irb.buildConstBool(
parent_scope, parent_scope,
Span.token(block.lbrace), Span.token(block.lbrace),
@ -1542,8 +1542,8 @@ pub const Builder = struct {
const defer_counts = irb.countDefers(scope, outer_scope); const defer_counts = irb.countDefers(scope, outer_scope);
const have_err_defers = defer_counts.error_exit != 0; const have_err_defers = defer_counts.error_exit != 0;
if (have_err_defers or irb.comp.have_err_ret_tracing) { if (have_err_defers or irb.comp.have_err_ret_tracing) {
const err_block = try irb.createBasicBlock(scope, c"ErrRetErr"); const err_block = try irb.createBasicBlock(scope, "ErrRetErr");
const ok_block = try irb.createBasicBlock(scope, c"ErrRetOk"); const ok_block = try irb.createBasicBlock(scope, "ErrRetOk");
if (!have_err_defers) { if (!have_err_defers) {
_ = try await (async irb.genDefersForBlock(scope, outer_scope, Scope.Defer.Kind.ScopeExit) catch unreachable); _ = 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, .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); try irb.setCursorAtEndAndAppendBlock(err_block);
if (have_err_defers) { if (have_err_defers) {
@ -2530,7 +2530,7 @@ pub async fn gen(
var irb = try Builder.init(comp, tree_scope, scope); var irb = try Builder.init(comp, tree_scope, scope);
errdefer irb.abort(); 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. entry_block.ref(&irb); // Entry block gets a reference because we enter it to begin.
try irb.setCursorAtEndAndAppendBlock(entry_block); 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 // even though we're calling LLD as a library it thinks the first
// argument is its own exe name // argument is its own exe name
try ctx.args.append(c"lld"); try ctx.args.append("lld");
if (comp.haveLibC()) { if (comp.haveLibC()) {
ctx.libc = ctx.comp.override_libc orelse blk: { ctx.libc = ctx.comp.override_libc orelse blk: {
@ -145,7 +145,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// lj->args.append("-T"); // lj->args.append("-T");
// lj->args.append(g->linker_script); // 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("-m");
//lj->args.append(getLDMOption(&g->zig_target)); //lj->args.append(getLDMOption(&g->zig_target));
@ -155,9 +155,9 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
//Buf *soname = nullptr; //Buf *soname = nullptr;
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
if (ctx.comp.target.isArmOrThumb()) { if (ctx.comp.target.isArmOrThumb()) {
try ctx.args.append(c"-Bstatic"); try ctx.args.append("-Bstatic");
} else { } else {
try ctx.args.append(c"-static"); try ctx.args.append("-static");
} }
} }
//} else if (shared) { //} 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); // 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()); try ctx.args.append(ctx.out_file_path.ptr());
if (ctx.link_in_crt) { if (ctx.link_in_crt) {
@ -213,10 +213,10 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
//} //}
if (ctx.comp.haveLibC()) { 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((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); try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, ctx.libc.static_lib_dir.?)).ptr);
if (!ctx.comp.is_static) { if (!ctx.comp.is_static) {
@ -225,7 +225,7 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl; if (ctx.comp.target.getDynamicLinkerPath()) |dl| break :blk dl;
return error.LibCMissingDynamicLinker; 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); try ctx.args.append((try std.cstr.addNullByte(&ctx.arena.allocator, dl)).ptr);
} }
} }
@ -272,23 +272,23 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// libc dep // libc dep
if (ctx.comp.haveLibC()) { if (ctx.comp.haveLibC()) {
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
try ctx.args.append(c"--start-group"); try ctx.args.append("--start-group");
try ctx.args.append(c"-lgcc"); try ctx.args.append("-lgcc");
try ctx.args.append(c"-lgcc_eh"); try ctx.args.append("-lgcc_eh");
try ctx.args.append(c"-lc"); try ctx.args.append("-lc");
try ctx.args.append(c"-lm"); try ctx.args.append("-lm");
try ctx.args.append(c"--end-group"); try ctx.args.append("--end-group");
} else { } else {
try ctx.args.append(c"-lgcc"); try ctx.args.append("-lgcc");
try ctx.args.append(c"--as-needed"); try ctx.args.append("--as-needed");
try ctx.args.append(c"-lgcc_s"); try ctx.args.append("-lgcc_s");
try ctx.args.append(c"--no-as-needed"); try ctx.args.append("--no-as-needed");
try ctx.args.append(c"-lc"); try ctx.args.append("-lc");
try ctx.args.append(c"-lm"); try ctx.args.append("-lm");
try ctx.args.append(c"-lgcc"); try ctx.args.append("-lgcc");
try ctx.args.append(c"--as-needed"); try ctx.args.append("--as-needed");
try ctx.args.append(c"-lgcc_s"); try ctx.args.append("-lgcc_s");
try ctx.args.append(c"--no-as-needed"); try ctx.args.append("--no-as-needed");
} }
} }
@ -299,14 +299,14 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
} }
if (ctx.comp.target != Target.Native) { 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) { if (ctx.comp.target.getOs() == .zen) {
try ctx.args.append(c"-e"); try ctx.args.append("-e");
try ctx.args.append(c"_start"); 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 { fn constructLinkerArgsCoff(ctx: *Context) !void {
try ctx.args.append(c"-NOLOGO"); try ctx.args.append("-NOLOGO");
if (!ctx.comp.strip) { if (!ctx.comp.strip) {
try ctx.args.append(c"-DEBUG"); try ctx.args.append("-DEBUG");
} }
switch (ctx.comp.target.getArch()) { switch (ctx.comp.target.getArch()) {
builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"), builtin.Arch.i386 => try ctx.args.append("-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"), builtin.Arch.x86_64 => try ctx.args.append("-MACHINE:X64"),
builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"), builtin.Arch.aarch64 => try ctx.args.append("-MACHINE:ARM"),
else => return error.UnsupportedLinkArchitecture, else => return error.UnsupportedLinkArchitecture,
} }
if (ctx.comp.windows_subsystem_windows) { 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) { } 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; const is_library = ctx.comp.kind == Compilation.Kind.Lib;
@ -367,14 +367,14 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
// Visual C++ 2015 Conformance Changes // Visual C++ 2015 Conformance Changes
// https://msdn.microsoft.com/en-us/library/bb531344.aspx // 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 // msvcrt depends on kernel32
try ctx.args.append(c"kernel32.lib"); try ctx.args.append("kernel32.lib");
} else { } else {
try ctx.args.append(c"-NODEFAULTLIB"); try ctx.args.append("-NODEFAULTLIB");
if (!is_library) { if (!is_library) {
try ctx.args.append(c"-ENTRY:WinMainCRTStartup"); try ctx.args.append("-ENTRY:WinMainCRTStartup");
// TODO // TODO
//if (g->have_winmain) { //if (g->have_winmain) {
// lj->args.append("-ENTRY:WinMain"); // lj->args.append("-ENTRY:WinMain");
@ -385,7 +385,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
} }
if (is_library and !ctx.comp.is_static) { 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) { //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 { fn constructLinkerArgsMachO(ctx: *Context) !void {
try ctx.args.append(c"-demangle"); try ctx.args.append("-demangle");
if (ctx.comp.linker_rdynamic) { 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 is_lib = ctx.comp.kind == Compilation.Kind.Lib;
const shared = !ctx.comp.is_static and is_lib; const shared = !ctx.comp.is_static and is_lib;
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
try ctx.args.append(c"-static"); try ctx.args.append("-static");
} else { } else {
try ctx.args.append(c"-dynamic"); try ctx.args.append("-dynamic");
} }
//if (is_lib) { //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( const darwin_arch_str = try std.cstr.addNullByte(
&ctx.arena.allocator, &ctx.arena.allocator,
ctx.comp.target.getDarwinArchString(), ctx.comp.target.getDarwinArchString(),
@ -512,22 +512,22 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
const platform = try DarwinPlatform.get(ctx.comp); const platform = try DarwinPlatform.get(ctx.comp);
switch (platform.kind) { switch (platform.kind) {
DarwinPlatform.Kind.MacOS => try ctx.args.append(c"-macosx_version_min"), DarwinPlatform.Kind.MacOS => try ctx.args.append("-macosx_version_min"),
DarwinPlatform.Kind.IPhoneOS => try ctx.args.append(c"-iphoneos_version_min"), DarwinPlatform.Kind.IPhoneOS => try ctx.args.append("-iphoneos_version_min"),
DarwinPlatform.Kind.IPhoneOSSimulator => try ctx.args.append(c"-ios_simulator_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); const ver_str = try std.fmt.allocPrint(&ctx.arena.allocator, "{}.{}.{}\x00", platform.major, platform.minor, platform.micro);
try ctx.args.append(ver_str.ptr); try ctx.args.append(ver_str.ptr);
if (ctx.comp.kind == Compilation.Kind.Exe) { if (ctx.comp.kind == Compilation.Kind.Exe) {
if (ctx.comp.is_static) { if (ctx.comp.is_static) {
try ctx.args.append(c"-no_pie"); try ctx.args.append("-no_pie");
} else { } 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()); try ctx.args.append(ctx.out_file_path.ptr());
//for (size_t i = 0; i < g->rpath_list.length; i += 1) { //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); //add_rpath(lj, &lj->out_file);
if (shared) { 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) { } else if (ctx.comp.is_static) {
try ctx.args.append(c"-lcrt0.o"); try ctx.args.append("-lcrt0.o");
} else { } else {
switch (platform.kind) { switch (platform.kind) {
DarwinPlatform.Kind.MacOS => { DarwinPlatform.Kind.MacOS => {
if (platform.versionLessThan(10, 5)) { if (platform.versionLessThan(10, 5)) {
try ctx.args.append(c"-lcrt1.o"); try ctx.args.append("-lcrt1.o");
} else if (platform.versionLessThan(10, 6)) { } 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)) { } 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 => { DarwinPlatform.Kind.IPhoneOS => {
if (ctx.comp.target.getArch() == builtin.Arch.aarch64) { if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
// iOS does not need any crt1 files for arm64 // iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) { } 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)) { } 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 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 // to make syscalls because the syscall numbers are not documented
// and change between versions. // and change between versions.
// so we always link against libSystem // so we always link against libSystem
try ctx.args.append(c"-lSystem"); try ctx.args.append("-lSystem");
} else { } else {
if (mem.indexOfScalar(u8, lib.name, '/') == null) { if (mem.indexOfScalar(u8, lib.name, '/') == null) {
const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name); const arg = try std.fmt.allocPrint(&ctx.arena.allocator, "-l{}\x00", lib.name);
@ -601,15 +601,15 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
} }
} }
} else { } else {
try ctx.args.append(c"-undefined"); try ctx.args.append("-undefined");
try ctx.args.append(c"dynamic_lookup"); try ctx.args.append("dynamic_lookup");
} }
if (platform.kind == DarwinPlatform.Kind.MacOS) { if (platform.kind == DarwinPlatform.Kind.MacOS) {
if (platform.versionLessThan(10, 5)) { 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)) { } else if (platform.versionLessThan(10, 6)) {
try ctx.args.append(c"-lgcc_s.10.5"); try ctx.args.append("-lgcc_s.10.5");
} }
} else { } else {
@panic("TODO"); @panic("TODO");

View File

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

View File

@ -474,7 +474,7 @@ pub const Value = struct {
dont_null_terminate, dont_null_terminate,
) orelse return error.OutOfMemory; ) orelse return error.OutOfMemory;
const str_init_type = llvm.TypeOf(llvm_str_init); 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.SetInitializer(global, llvm_str_init);
llvm.SetLinkage(global, llvm.PrivateLinkage); llvm.SetLinkage(global, llvm.PrivateLinkage);
llvm.SetGlobalConstant(global, 1); llvm.SetGlobalConstant(global, 1);

View File

@ -102,6 +102,10 @@ struct IrExecutable {
bool is_inline; bool is_inline;
bool is_generic_instantiation; bool is_generic_instantiation;
bool need_err_code_spill; bool need_err_code_spill;
// This is a function for use in the debugger to print
// the source location.
void src();
}; };
enum OutType { enum OutType {
@ -237,9 +241,6 @@ struct ConstPtrValue {
struct { struct {
ConstExprValue *array_val; ConstExprValue *array_val;
size_t elem_index; size_t elem_index;
// This helps us preserve the null byte when performing compile-time
// concatenation on C strings.
bool is_cstr;
} base_array; } base_array;
struct { struct {
ConstExprValue *struct_val; ConstExprValue *struct_val;
@ -1001,7 +1002,6 @@ struct AstNodeStructField {
struct AstNodeStringLiteral { struct AstNodeStringLiteral {
Buf *buf; Buf *buf;
bool c;
}; };
struct AstNodeCharLiteral { struct AstNodeCharLiteral {
@ -1956,6 +1956,7 @@ struct CodeGen {
HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes; HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_prototypes;
HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> string_literals_table; 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> type_info_cache;
HashMap<const ZigType *, ConstExprValue *, type_ptr_hash, type_ptr_eql> one_possible_values;
ZigList<Tld *> resolve_queue; ZigList<Tld *> resolve_queue;
size_t resolve_queue_index; 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); ZigType *entry = new_type_table_entry(ZigTypeIdArray);
buf_resize(&entry->name, 0); const char *null_str = is_null_terminated ? "null " : "";
buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name));
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->size_in_bits = child_type->size_in_bits * full_array_size;
entry->abi_align = child_type->abi_align; entry->abi_align = child_type->abi_align;
entry->abi_size = child_type->abi_size * full_array_size; 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 += (uint32_t)1764906839;
hash_val += hash_ptr(const_val->data.x_ptr.data.base_array.array_val); 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 += 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; return hash_val;
case ConstPtrSpecialBaseStruct: case ConstPtrSpecialBaseStruct:
hash_val += (uint32_t)3518317043; hash_val += (uint32_t)3518317043;
@ -5550,6 +5557,18 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
zig_unreachable(); 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) { ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
Error err; Error err;
switch (ty->id) { switch (ty->id) {
@ -5617,10 +5636,19 @@ void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str) {
return; 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->special = ConstValSpecialStatic;
const_val->type = get_array_type(g, g->builtin_types.entry_u8, buf_len(str), false); const_val->type = get_pointer_to_type_extra2(g, array_val->type, true, false,
const_val->data.x_array.special = ConstArraySpecialBuf; PtrLenSingle, 0, 0, 0, false, VECTOR_INDEX_NONE, nullptr);
const_val->data.x_array.data.s_buf = str; 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); g->string_literals_table.put(str, const_val);
} }
@ -5631,41 +5659,6 @@ ConstExprValue *create_const_str_lit(CodeGen *g, Buf *str) {
return const_val; 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) { void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint) {
const_val->special = ConstValSpecialStatic; const_val->special = ConstValSpecialStatic;
const_val->type = type; const_val->type = type;
@ -5712,6 +5705,18 @@ ConstExprValue *create_const_signed(ZigType *type, int64_t x) {
return const_val; 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) { void init_const_float(ConstExprValue *const_val, ZigType *type, double value) {
const_val->special = ConstValSpecialStatic; const_val->special = ConstValSpecialStatic;
const_val->type = type; 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) { bool const_values_equal_ptr(ConstExprValue *a, ConstExprValue *b) {
if (a->data.x_ptr.special != b->data.x_ptr.special) if (a->data.x_ptr.special != b->data.x_ptr.special)
return false; return false;
if (a->data.x_ptr.mut != b->data.x_ptr.mut)
return false;
switch (a->data.x_ptr.special) { switch (a->data.x_ptr.special) {
case ConstPtrSpecialInvalid: case ConstPtrSpecialInvalid:
zig_unreachable(); 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) if (a->data.x_ptr.data.base_array.elem_index != b->data.x_ptr.data.base_array.elem_index)
return false; 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; return true;
case ConstPtrSpecialBaseStruct: case ConstPtrSpecialBaseStruct:
if (a->data.x_ptr.data.base_struct.struct_val != b->data.x_ptr.data.base_struct.struct_val && 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->type->id == b->type->id);
assert(a->special == ConstValSpecialStatic); assert(a->special == ConstValSpecialStatic);
assert(b->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) { switch (a->type->id) {
case ZigTypeIdOpaque: case ZigTypeIdOpaque:
zig_unreachable(); 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)); render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return; return;
case ConstPtrSpecialBaseArray: case ConstPtrSpecialBaseArray:
if (const_val->data.x_ptr.data.base_array.is_cstr) {
buf_appendf(buf, "*(c str lit)");
return;
} else {
buf_appendf(buf, "*"); buf_appendf(buf, "*");
// TODO we need a source node for const_ptr_pointee because it can generate compile errors // 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)); render_const_value(g, buf, const_ptr_pointee(nullptr, g, const_val, nullptr));
return; return;
}
case ConstPtrSpecialHardCodedAddr: case ConstPtrSpecialHardCodedAddr:
buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name), buf_appendf(buf, "(%s)(%" ZIG_PRI_x64 ")", buf_ptr(&type_entry->name),
const_val->data.x_ptr.data.hard_coded_addr.addr); 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; 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 // 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_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); 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, 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) { 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); *out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
return ErrorNone; 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); void init_const_str_lit(CodeGen *g, ConstExprValue *const_val, Buf *str);
ConstExprValue *create_const_str_lit(CodeGen *g, 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); void init_const_bigint(ConstExprValue *const_val, ZigType *type, const BigInt *bigint);
ConstExprValue *create_const_bigint(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); 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); 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 *create_const_vals(size_t count);
ConstExprValue **alloc_const_vals_ptrs(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); 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); ZigType *var_type, const char *name_hint);
Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str, Error analyze_import(CodeGen *codegen, ZigType *source_import, Buf *import_target_str,
ZigType **out_import, Buf **out_import_target_path, Buf *out_full_path); 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 #endif

View File

@ -619,9 +619,6 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
break; break;
case NodeTypeStringLiteral: case NodeTypeStringLiteral:
{ {
if (node->data.string_literal.c) {
fprintf(ar->f, "c");
}
Buf tmp_buf = BUF_INIT; Buf tmp_buf = BUF_INIT;
string_literal_escape(node->data.string_literal.buf, &tmp_buf); string_literal_escape(node->data.string_literal.buf, &tmp_buf);
fprintf(ar->f, "\"%s\"", buf_ptr(&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) { if (!val->global_refs->llvm_global) {
Buf *buf_msg = panic_msg_buf(msg_id); 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); init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);
render_const_val(g, val, ""); 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 *op1 = bin_op_instruction->op1;
IrInstruction *op2 = bin_op_instruction->op2; 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 *operand_type = op1->value.type;
ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_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; AddSubMulMul;
if (scalar_type->id == ZigTypeIdPointer) { if (scalar_type->id == ZigTypeIdPointer) {
assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
LLVMValueRef subscript_value; LLVMValueRef subscript_value;
if (operand_type->id == ZigTypeIdVector) if (operand_type->id == ZigTypeIdVector)
zig_panic("TODO: Implement vector operations on pointers."); zig_panic("TODO: Implement vector operations on pointers.");
@ -3077,7 +3068,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
case CastOpNumLitToConcrete: case CastOpNumLitToConcrete:
zig_unreachable(); zig_unreachable();
case CastOpNoop: case CastOpNoop:
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; return expr_val;
}
case CastOpIntToFloat: case CastOpIntToFloat:
assert(actual_type->id == ZigTypeIdInt); assert(actual_type->id == ZigTypeIdInt);
if (actual_type->data.integral.is_signed) { 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; array_type = array_type->data.pointer.child_type;
} }
if (safety_check_on) { if (safety_check_on) {
LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, uint64_t extra_len_from_null = array_type->data.array.is_null_terminated ? 1 : 0;
array_type->data.array.len, false); 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); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end);
} }
if (array_ptr_type->data.pointer.host_int_bytes != 0) { if (array_ptr_type->data.pointer.host_int_bytes != 0) {
@ -6637,12 +6636,21 @@ 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; ConstExprValue *array_const_val = const_val->data.x_ptr.data.base_array.array_val;
assert(array_const_val->type->id == ZigTypeIdArray); assert(array_const_val->type->id == ZigTypeIdArray);
if (!type_has_bits(array_const_val->type)) { if (!type_has_bits(array_const_val->type)) {
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 // make this a null pointer
ZigType *usize = g->builtin_types.entry_usize; ZigType *usize = g->builtin_types.entry_usize;
const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type),
get_llvm_type(g, const_val->type)); get_llvm_type(g, const_val->type));
return const_val->global_refs->llvm_value; return const_val->global_refs->llvm_value;
} }
}
size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; 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); LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index);
LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type));
@ -6955,7 +6963,9 @@ check: switch (const_val->special) {
case ConstArraySpecialUndef: case ConstArraySpecialUndef:
return LLVMGetUndef(get_llvm_type(g, type_entry)); return LLVMGetUndef(get_llvm_type(g, type_entry));
case ConstArraySpecialNone: { 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); LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type);
bool make_unnamed_struct = false; bool make_unnamed_struct = false;
for (uint64_t i = 0; i < len; i += 1) { for (uint64_t i = 0; i < len; i += 1) {
@ -6964,15 +6974,19 @@ check: switch (const_val->special) {
values[i] = val; values[i] = val;
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, 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) { if (make_unnamed_struct) {
return LLVMConstStruct(values, len, true); return LLVMConstStruct(values, full_len, true);
} else { } else {
return LLVMConstArray(element_type_ref, values, (unsigned)len); return LLVMConstArray(element_type_ref, values, (unsigned)full_len);
} }
} }
case ConstArraySpecialBuf: { case ConstArraySpecialBuf: {
Buf *buf = const_val->data.x_array.data.s_buf; 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(); 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); this_val->data.x_struct.fields = alloc_const_vals_ptrs(2);
ConstExprValue *name_field = this_val->data.x_struct.fields[0]; 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); 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]; 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->external_prototypes.init(8);
g->string_literals_table.init(16); g->string_literals_table.init(16);
g->type_info_cache.init(32); g->type_info_cache.init(32);
g->one_possible_values.init(32);
g->is_test_build = is_test_build; g->is_test_build = is_test_build;
g->is_single_threaded = false; g->is_single_threaded = false;
buf_resize(&g->global_asm, 0); buf_resize(&g->global_asm, 0);

View File

@ -66,6 +66,8 @@ enum ConstCastResultId {
ConstCastResultIdUnresolvedInferredErrSet, ConstCastResultIdUnresolvedInferredErrSet,
ConstCastResultIdAsyncAllocatorType, ConstCastResultIdAsyncAllocatorType,
ConstCastResultIdBadAllowsZero, ConstCastResultIdBadAllowsZero,
ConstCastResultIdArrayChild,
ConstCastResultIdBadNullTermArrays,
}; };
struct ConstCastOnly; struct ConstCastOnly;
@ -87,7 +89,9 @@ struct ConstCastErrUnionErrSetMismatch;
struct ConstCastErrUnionPayloadMismatch; struct ConstCastErrUnionPayloadMismatch;
struct ConstCastErrSetMismatch; struct ConstCastErrSetMismatch;
struct ConstCastTypeMismatch; struct ConstCastTypeMismatch;
struct ConstCastArrayMismatch;
struct ConstCastBadAllowsZero; struct ConstCastBadAllowsZero;
struct ConstCastBadNullTermArrays;
struct ConstCastOnly { struct ConstCastOnly {
ConstCastResultId id; ConstCastResultId id;
@ -99,11 +103,13 @@ struct ConstCastOnly {
ConstCastErrUnionPayloadMismatch *error_union_payload; ConstCastErrUnionPayloadMismatch *error_union_payload;
ConstCastErrUnionErrSetMismatch *error_union_error_set; ConstCastErrUnionErrSetMismatch *error_union_error_set;
ConstCastTypeMismatch *type_mismatch; ConstCastTypeMismatch *type_mismatch;
ConstCastArrayMismatch *array_mismatch;
ConstCastOnly *return_type; ConstCastOnly *return_type;
ConstCastOnly *null_wrap_ptr_child; ConstCastOnly *null_wrap_ptr_child;
ConstCastArg fn_arg; ConstCastArg fn_arg;
ConstCastArgNoAlias arg_no_alias; ConstCastArgNoAlias arg_no_alias;
ConstCastBadAllowsZero *bad_allows_zero; ConstCastBadAllowsZero *bad_allows_zero;
ConstCastBadNullTermArrays *bad_null_term_arrays;
} data; } data;
}; };
@ -130,6 +136,12 @@ struct ConstCastSliceMismatch {
ZigType *actual_child; ZigType *actual_child;
}; };
struct ConstCastArrayMismatch {
ConstCastOnly child;
ZigType *wanted_child;
ZigType *actual_child;
};
struct ConstCastErrUnionErrSetMismatch { struct ConstCastErrUnionErrSetMismatch {
ConstCastOnly child; ConstCastOnly child;
ZigType *wanted_err_set; ZigType *wanted_err_set;
@ -151,6 +163,12 @@ struct ConstCastBadAllowsZero {
ZigType *actual_type; 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(IrBuilder *irb, AstNode *node, Scope *scope);
static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, Scope *scope, LVal lval, 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: case OnePossibleValueInvalid:
zig_unreachable(); zig_unreachable();
case OnePossibleValueYes: case OnePossibleValueYes:
result = create_const_vals(1); return get_the_one_possible_value(g, const_val->type->data.pointer.child_type);
result->type = const_val->type->data.pointer.child_type;
result->special = ConstValSpecialStatic;
return result;
case OnePossibleValueNo: case OnePossibleValueNo:
break; break;
} }
@ -233,8 +248,13 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
break; break;
case ConstPtrSpecialBaseArray: { case ConstPtrSpecialBaseArray: {
ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val; ConstExprValue *array_val = const_val->data.x_ptr.data.base_array.array_val;
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); 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]; result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
}
break; break;
} }
case ConstPtrSpecialBaseStruct: { 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 // This function returns true when you can change the type of a ConstExprValue and the
// value remains meaningful. // value remains meaningful.
static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) { static bool types_have_same_zig_comptime_repr(ZigType *expected, ZigType *actual) {
if (a == b) if (expected == actual)
return true; 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; 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; return true;
if (a->id != b->id) if (expected->id != actual->id)
return false; return false;
switch (a->id) { switch (expected->id) {
case ZigTypeIdInvalid: case ZigTypeIdInvalid:
case ZigTypeIdUnreachable: case ZigTypeIdUnreachable:
zig_unreachable(); zig_unreachable();
@ -314,12 +334,11 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdAnyFrame: case ZigTypeIdAnyFrame:
return true; return true;
case ZigTypeIdFloat: 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: 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: case ZigTypeIdStruct:
return is_slice(a) && is_slice(b); return is_slice(expected) && is_slice(actual);
case ZigTypeIdArray:
case ZigTypeIdOptional: case ZigTypeIdOptional:
case ZigTypeIdErrorUnion: case ZigTypeIdErrorUnion:
case ZigTypeIdEnum: case ZigTypeIdEnum:
@ -329,6 +348,10 @@ static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
case ZigTypeIdVector: case ZigTypeIdVector:
case ZigTypeIdFnFrame: case ZigTypeIdFnFrame:
return false; 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(); zig_unreachable();
} }
@ -1299,12 +1322,6 @@ static IrInstruction *ir_build_const_str_lit(IrBuilder *irb, Scope *scope, AstNo
return instruction; 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, static IrInstruction *ir_build_bin_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrBinOp op_id,
IrInstruction *op1, IrInstruction *op2, bool safety_check_on) 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) { static IrInstruction *ir_gen_string_literal(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypeStringLiteral); 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) { 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(val != nullptr);
assert(const_val->type->id == ZigTypeIdPointer); assert(const_val->type->id == ZigTypeIdPointer);
ZigType *expected_type = const_val->type->data.pointer.child_type; 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))) if ((err = eval_comptime_ptr_reinterpret(ira, codegen, source_node, const_val)))
return nullptr; return nullptr;
return const_ptr_pointee_unchecked(codegen, const_val); 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 // slice const
if (is_slice(wanted_type) && is_slice(actual_type)) { if (is_slice(wanted_type) && is_slice(actual_type)) {
ZigType *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index]->type_entry; 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; 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 // [N]T to []T
if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) && if (prev_type->id == ZigTypeIdArray && is_slice(cur_type) &&
(cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const || (cur_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const ||
@ -10740,7 +10826,7 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
free(errors); free(errors);
if (convert_to_const_slice) { if (convert_to_const_slice) {
assert(prev_inst->value.type->id == ZigTypeIdArray); if (prev_inst->value.type->id == ZigTypeIdArray) {
ZigType *ptr_type = get_pointer_to_type_extra( ZigType *ptr_type = get_pointer_to_type_extra(
ira->codegen, prev_inst->value.type->data.array.child_type, ira->codegen, prev_inst->value.type->data.array.child_type,
true, false, PtrLenUnknown, true, false, PtrLenUnknown,
@ -10751,6 +10837,23 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
} else { } else {
return slice_type; 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 {
zig_unreachable();
}
} else if (err_set_type != nullptr) { } else if (err_set_type != nullptr) {
if (prev_inst->value.type->id == ZigTypeIdErrorSet) { if (prev_inst->value.type->id == ZigTypeIdErrorSet) {
return err_set_type; return err_set_type;
@ -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.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.array_val = pointee;
result->value.data.x_ptr.data.base_array.elem_index = 0; result->value.data.x_ptr.data.base_array.elem_index = 0;
result->value.data.x_ptr.data.base_array.is_cstr = false;
return result; 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, 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; 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))) ResolveStatusAlignmentKnown)))
{ {
return ira->codegen->invalid_instruction; 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)) { if (instr_is_comptime(array_ptr)) {
ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &value->value, source_instr->source_node); ConstExprValue *pointee = const_ptr_pointee(ira, ira->codegen, &array_ptr->value, source_instr->source_node);
if (pointee == nullptr) if (pointee == nullptr)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
if (pointee->special != ConstValSpecialRuntime) { if (pointee->special != ConstValSpecialRuntime) {
assert(value->value.type->id == ZigTypeIdPointer); assert(array_ptr->value.type->id == ZigTypeIdPointer);
ZigType *array_type = value->value.type->data.pointer.child_type; ZigType *array_type = array_ptr->value.type->data.pointer.child_type;
assert(is_slice(wanted_type)); assert(is_slice(wanted_type));
bool is_const = wanted_type->data.structure.fields[slice_ptr_index]->type_entry->data.pointer.is_const; 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); 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); 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; result->value.type = wanted_type;
return result; 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)) { if (type_is_invalid(result_loc_inst->value.type) || instr_is_unreachable(result_loc_inst)) {
return 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) { 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 ConstCastResultIdFnArgNoAlias: // TODO
case ConstCastResultIdUnresolvedInferredErrSet: // TODO case ConstCastResultIdUnresolvedInferredErrSet: // TODO
case ConstCastResultIdAsyncAllocatorType: // TODO case ConstCastResultIdAsyncAllocatorType: // TODO
case ConstCastResultIdArrayChild: // TODO
case ConstCastResultIdBadNullTermArrays: // TODO
break; 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); return ir_analyze_widen_or_shorten(ira, source_instr, value, wanted_type);
} }
// cast from [N]T to []const T // cast from [N]T to []const T
// TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this // TODO: once https://github.com/ziglang/zig/issues/265 lands, remove this
if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) { if (is_slice(wanted_type) && actual_type->id == ZigTypeIdArray) {
@ -12834,12 +12937,34 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
} }
} }
// *[N]T to [*]T and [*c]T // *[N]T to ?[]const T
if (wanted_type->id == ZigTypeIdPointer && if (wanted_type->id == ZigTypeIdOptional &&
(wanted_type->data.pointer.ptr_len == PtrLenUnknown || wanted_type->data.pointer.ptr_len == PtrLenC) && is_slice(wanted_type->data.maybe.child_type) &&
actual_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
actual_type->data.pointer.ptr_len == PtrLenSingle && actual_type->data.pointer.ptr_len == PtrLenSingle &&
actual_type->data.pointer.child_type->id == ZigTypeIdArray) actual_type->data.pointer.child_type->id == ZigTypeIdArray)
{
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;
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;
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)
{ {
if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) if ((err = type_resolve(ira->codegen, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown)))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
@ -12853,6 +12978,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type); return ir_resolve_ptr_of_array_to_unknown_len_ptr(ira, source_instr, value, wanted_type);
} }
} }
}
// *[N]T to []T // *[N]T to []T
// *[N]T to E![]T // *[N]T to E![]T
@ -14544,8 +14670,6 @@ static bool ok_float_op(IrBinOp op) {
} }
static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) { static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
if (lhs_type->id != ZigTypeIdPointer)
return false;
switch (op) { switch (op) {
case IrBinOpAdd: case IrBinOpAdd:
case IrBinOpSub: case IrBinOpSub:
@ -14553,15 +14677,17 @@ static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
default: default:
return false; return false;
} }
if (lhs_type->id != ZigTypeIdPointer)
return false;
switch (lhs_type->data.pointer.ptr_len) { switch (lhs_type->data.pointer.ptr_len) {
case PtrLenSingle: case PtrLenSingle:
return false; return lhs_type->data.pointer.child_type->id == ZigTypeIdArray;
case PtrLenUnknown: case PtrLenUnknown:
case PtrLenNull: case PtrLenNull:
case PtrLenC: case PtrLenC:
break;
}
return true; return true;
}
zig_unreachable();
} }
static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) { 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) if (!op2_val)
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
bool is_null_terminated = false;
ConstExprValue *op1_array_val; ConstExprValue *op1_array_val;
size_t op1_array_index; size_t op1_array_index;
size_t op1_array_end; 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; op1_array_end = op1_type->data.array.len;
} else if (op1_type->id == ZigTypeIdPointer && } else if (op1_type->id == ZigTypeIdPointer &&
op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 && op1_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 &&
op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray && op1_type->data.pointer.ptr_len == PtrLenNull &&
op1_val->data.x_ptr.data.base_array.is_cstr) op1_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
{ {
child_type = op1_type->data.pointer.child_type; child_type = op1_type->data.pointer.child_type;
op1_array_val = op1_val->data.x_ptr.data.base_array.array_val; 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_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)) { } else if (is_slice(op1_type)) {
ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry; ZigType *ptr_type = op1_type->data.structure.fields[slice_ptr_index]->type_entry;
child_type = ptr_type->data.pointer.child_type; 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; 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]; 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); 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 { } else {
ir_add_error(ira, op1, 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; 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_index = 0;
op2_array_end = op2_array_val->type->data.array.len; op2_array_end = op2_array_val->type->data.array.len;
} else if (op2_type->id == ZigTypeIdPointer && } else if (op2_type->id == ZigTypeIdPointer &&
op2_type->data.pointer.child_type == ira->codegen->builtin_types.entry_u8 && op2_type->data.pointer.ptr_len == PtrLenNull &&
op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray && op2_val->data.x_ptr.special == ConstPtrSpecialBaseArray)
op2_val->data.x_ptr.data.base_array.is_cstr)
{ {
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_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_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)) { } else if (is_slice(op2_type)) {
ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry; ZigType *ptr_type = op2_type->data.structure.fields[slice_ptr_index]->type_entry;
op2_type_valid = ptr_type->data.pointer.child_type == child_type; 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; 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]; 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); 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 { } else {
ir_add_error(ira, op2, ir_add_error(ira, op2,
buf_sprintf("expected array or C string literal, found '%s'", buf_ptr(&op2->value.type->name))); 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); result->value.type = get_array_type(ira->codegen, child_type, new_len, false);
out_array_val = out_val; 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)) { } else if (is_slice(op1_type) || is_slice(op2_type)) {
ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, child_type,
true, false, PtrLenUnknown, 0, 0, 0, false); 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; 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); bigint_init_unsigned(&out_val->data.x_struct.fields[slice_len_index]->data.x_bigint, new_len);
} else { } else {
new_len += 1; // null byte result->value.type = get_pointer_to_type_extra(ira->codegen, child_type, true, false, PtrLenNull,
0, 0, 0, false);
// 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);
out_array_val = create_const_vals(1); out_array_val = create_const_vals(1);
out_array_val->special = ConstValSpecialStatic; out_array_val->special = ConstValSpecialStatic;
out_array_val->type = get_array_type(ira->codegen, child_type, new_len, false); 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.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.array_val = out_array_val;
out_val->data.x_ptr.data.base_array.elem_index = 0; out_val->data.x_ptr.data.base_array.elem_index = 0;
} }
if (op1_array_val->data.x_array.special == ConstArraySpecialUndef && 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; out_array_val->data.x_array.special = ConstArraySpecialUndef;
return result; return result;
} }
@ -14978,20 +15134,34 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
if (type_is_invalid(op2->value.type)) if (type_is_invalid(op2->value.type))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
ConstExprValue *array_val = ir_resolve_const(ira, op1, UndefBad); bool want_ptr_to_array = false;
if (!array_val) 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; 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; uint64_t mult_amt;
if (!ir_resolve_usize(ira, op2, &mult_amt)) if (!ir_resolve_usize(ira, op2, &mult_amt))
return ira->codegen->invalid_instruction; 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 old_array_len = array_type->data.array.len;
uint64_t new_array_len; uint64_t new_array_len;
@ -15001,27 +15171,29 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
} }
ZigType *child_type = array_type->data.array.child_type; 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, IrInstruction *array_result;
get_array_type(ira->codegen, child_type, new_array_len, false)); if (array_val->special == ConstValSpecialUndef || array_val->data.x_array.special == ConstArraySpecialUndef) {
ConstExprValue *out_val = &result->value; array_result = ir_const_undef(ira, &instruction->base, result_array_type);
if (array_val->data.x_array.special == ConstArraySpecialUndef) { } else {
out_val->data.x_array.special = ConstArraySpecialUndef; array_result = ir_const(ira, &instruction->base, result_array_type);
return result; ConstExprValue *out_val = &array_result->value;
}
switch (type_has_one_possible_value(ira->codegen, result->value.type)) { switch (type_has_one_possible_value(ira->codegen, result_array_type)) {
case OnePossibleValueInvalid: case OnePossibleValueInvalid:
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
case OnePossibleValueYes: case OnePossibleValueYes:
return result; goto skip_computation;
case OnePossibleValueNo: case OnePossibleValueNo:
break; break;
} }
// TODO optimize the buf case // TODO optimize the buf case
expand_undef_array(ira->codegen, array_val); expand_undef_array(ira->codegen, array_val);
out_val->data.x_array.data.s_none.elements = create_const_vals(new_array_len); 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; uint64_t i = 0;
for (uint64_t x = 0; x < mult_amt; x += 1) { for (uint64_t x = 0; x < mult_amt; x += 1) {
@ -15036,7 +15208,22 @@ static IrInstruction *ir_analyze_array_mult(IrAnalyze *ira, IrInstructionBinOp *
} }
assert(i == new_array_len); assert(i == new_array_len);
return result; 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, 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;
}
}
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, 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); assert(out_val->type != nullptr);
ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val); ConstExprValue *pointee = const_ptr_pointee_unchecked(codegen, ptr_val);
src_assert(pointee->type != nullptr, source_node);
if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown))) if ((err = type_resolve(codegen, pointee->type, ResolveStatusSizeKnown)))
return ErrorSemanticAnalyzeFail; 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); size_t dst_size = type_size(codegen, out_val->type);
if (dst_size <= src_size) { 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); copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut != ConstPtrMutComptimeVar);
return ErrorNone; 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); uint64_t index = bigint_as_u64(&casted_elem_index->value.data.x_bigint);
if (array_type->id == ZigTypeIdArray) { if (array_type->id == ZigTypeIdArray) {
uint64_t array_len = array_type->data.array.len; 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) { if (index >= array_len) {
ir_add_error_node(ira, elem_ptr_instruction->base.source_node, ir_add_error_node(ira, elem_ptr_instruction->base.source_node,
buf_sprintf("index %" ZIG_PRI_u64 " outside array of size %" ZIG_PRI_u64, 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; size_t offset = array_ptr_val->data.x_ptr.data.base_array.elem_index;
new_index = offset + 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; old_size = mem_size - offset;
assert(array_ptr_val->data.x_ptr.data.base_array.array_val); 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 = out_val->data.x_ptr.data.base_array.array_val =
array_ptr_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.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; 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 = out_val->data.x_ptr.data.base_array.array_val =
ptr_field->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.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; break;
} }
case ConstPtrSpecialBaseStruct: 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, 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); 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)) { if (instr_is_comptime(base_ptr)) {
ConstExprValue *ptr_val = ir_resolve_const(ira, base_ptr, UndefBad); 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; return ira->codegen->invalid_instruction;
ErrorTableEntry *err = casted_value->value.data.x_err_set; ErrorTableEntry *err = casted_value->value.data.x_err_set;
if (!err->cached_error_name_val) { 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); 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); 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))) if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
return ira->codegen->invalid_instruction; return ira->codegen->invalid_instruction;
TypeEnumField *field = find_enum_field_by_tag(target->value.type, &target->value.data.x_bigint); 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); IrInstruction *result = ir_const(ira, &instruction->base, nullptr);
init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true); init_const_slice(ira->codegen, &result->value, array_val, 0, buf_len(field->name), true);
return result; 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; declaration_val->type = type_info_declaration_type;
ConstExprValue **inner_fields = alloc_const_vals_ptrs(3); 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); init_const_slice(ira->codegen, inner_fields[0], name, 0, buf_len(curr_entry->key), true);
inner_fields[1]->special = ConstValSpecialStatic; inner_fields[1]->special = ConstValSpecialStatic;
inner_fields[1]->type = ira->codegen->builtin_types.entry_bool; 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)); 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) { 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); 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, init_const_slice(ira->codegen, fn_decl_fields[6]->data.x_optional, lib_name, 0,
buf_len(fn_node->lib_name), true); buf_len(fn_node->lib_name), true);
} else { } 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); 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 *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, 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); 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.id = ConstParentIdArray;
fn_arg_name_val->parent.data.p_array.array_val = fn_arg_name_array; 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]->special = ConstValSpecialStatic;
inner_fields[1]->type = ira->codegen->builtin_types.entry_num_lit_int; 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); 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); 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) if (error->cached_error_name_val != nullptr)
name = error->cached_error_name_val; name = error->cached_error_name_val;
if (name == nullptr) 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); 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); 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]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = union_field->type_entry; 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); 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; 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]->type = ira->codegen->builtin_types.entry_type;
inner_fields[2]->data.x_type = struct_field->type_entry; 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); 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; 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) { if (string_lit != nullptr) {
AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit); AstNode *res = ast_create_node(pc, NodeTypeStringLiteral, string_lit);
res->data.string_literal.buf = token_buf(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; return res;
} }

View File

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

View File

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

View File

@ -323,17 +323,9 @@ static AstNode *trans_create_node_bool(Context *c, bool value) {
return bool_node; 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); AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
node->data.string_literal.buf = buf; 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; return node;
} }
@ -632,7 +624,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const ZigClangQualType qt,
// zig_type_node // zig_type_node
AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import"); 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 *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 *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); 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: { case ZigClangStringLiteral_StringKind_UTF8: {
size_t str_len; size_t str_len;
const char *str_ptr = ZigClangStringLiteral_getString_bytes_begin_size(stmt, &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); return maybe_suppress_result(c, result_used, node);
} }
case ZigClangStringLiteral_StringKind_UTF16: 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); return trans_create_node_unsigned(c, tok->data.char_lit);
case CTokIdStrLit: case CTokIdStrLit:
*tok_i += 1; *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: case CTokIdMinus:
*tok_i += 1; *tok_i += 1;
return parse_ctok_num_lit(c, ctok, tok_i, true); 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) // (dest)(x)
AstNode *import_builtin = trans_create_node_builtin_fn_call_str(c, "import"); 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_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_pointer = trans_create_node_field_access_str(c, typeid_type, "Pointer");
AstNode *typeid_integer = trans_create_node_field_access_str(c, typeid_type, "Int"); 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", cases.addC("hello world with libc",
\\const c = @cImport(@cInclude("stdio.h")); \\const c = @cImport(@cInclude("stdio.h"));
\\export fn main(argc: c_int, argv: [*][*]u8) c_int { \\export fn main(argc: c_int, argv: [*][*]u8) c_int {
\\ _ = c.puts(c"Hello, world!"); \\ _ = c.puts("Hello, world!");
\\ return 0; \\ return 0;
\\} \\}
, "Hello, world!" ++ std.cstr.line_sep); , "Hello, world!" ++ std.cstr.line_sep);
@ -144,75 +144,75 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ // we want actual \n, not \r\n \\ // we want actual \n, not \r\n
\\ _ = c._setmode(1, c._O_BINARY); \\ _ = c._setmode(1, c._O_BINARY);
\\ } \\ }
\\ _ = c.printf(c"0: %llu\n", \\ _ = c.printf("0: %llu\n",
\\ @as(u64, 0)); \\ @as(u64, 0));
\\ _ = c.printf(c"320402575052271: %llu\n", \\ _ = c.printf("320402575052271: %llu\n",
\\ @as(u64, 320402575052271)); \\ @as(u64, 320402575052271));
\\ _ = c.printf(c"0x01236789abcdef: %llu\n", \\ _ = c.printf("0x01236789abcdef: %llu\n",
\\ @as(u64, 0x01236789abcdef)); \\ @as(u64, 0x01236789abcdef));
\\ _ = c.printf(c"0xffffffffffffffff: %llu\n", \\ _ = c.printf("0xffffffffffffffff: %llu\n",
\\ @as(u64, 0xffffffffffffffff)); \\ @as(u64, 0xffffffffffffffff));
\\ _ = c.printf(c"0x000000ffffffffffffffff: %llu\n", \\ _ = c.printf("0x000000ffffffffffffffff: %llu\n",
\\ @as(u64, 0x000000ffffffffffffffff)); \\ @as(u64, 0x000000ffffffffffffffff));
\\ _ = c.printf(c"0o1777777777777777777777: %llu\n", \\ _ = c.printf("0o1777777777777777777777: %llu\n",
\\ @as(u64, 0o1777777777777777777777)); \\ @as(u64, 0o1777777777777777777777));
\\ _ = c.printf(c"0o0000001777777777777777777777: %llu\n", \\ _ = c.printf("0o0000001777777777777777777777: %llu\n",
\\ @as(u64, 0o0000001777777777777777777777)); \\ @as(u64, 0o0000001777777777777777777777));
\\ _ = c.printf(c"0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n", \\ _ = c.printf("0b1111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111)); \\ @as(u64, 0b1111111111111111111111111111111111111111111111111111111111111111));
\\ _ = c.printf(c"0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n", \\ _ = c.printf("0b0000001111111111111111111111111111111111111111111111111111111111111111: %llu\n",
\\ @as(u64, 0b0000001111111111111111111111111111111111111111111111111111111111111111)); \\ @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)); \\ @as(f64, 0.0));
\\ _ = c.printf(c"0e0: %.013a\n", \\ _ = c.printf("0e0: %.013a\n",
\\ @as(f64, 0e0)); \\ @as(f64, 0e0));
\\ _ = c.printf(c"0.0e0: %.013a\n", \\ _ = c.printf("0.0e0: %.013a\n",
\\ @as(f64, 0.0e0)); \\ @as(f64, 0.0e0));
\\ _ = c.printf(c"000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n", \\ _ = c.printf("000000000000000000000000000000000000000000000000000000000.0e0: %.013a\n",
\\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0)); \\ @as(f64, 000000000000000000000000000000000000000000000000000000000.0e0));
\\ _ = c.printf(c"0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n", \\ _ = c.printf("0.000000000000000000000000000000000000000000000000000000000e0: %.013a\n",
\\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0)); \\ @as(f64, 0.000000000000000000000000000000000000000000000000000000000e0));
\\ _ = c.printf(c"0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n", \\ _ = c.printf("0.0e000000000000000000000000000000000000000000000000000000000: %.013a\n",
\\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000)); \\ @as(f64, 0.0e000000000000000000000000000000000000000000000000000000000));
\\ _ = c.printf(c"1.0: %.013a\n", \\ _ = c.printf("1.0: %.013a\n",
\\ @as(f64, 1.0)); \\ @as(f64, 1.0));
\\ _ = c.printf(c"10.0: %.013a\n", \\ _ = c.printf("10.0: %.013a\n",
\\ @as(f64, 10.0)); \\ @as(f64, 10.0));
\\ _ = c.printf(c"10.5: %.013a\n", \\ _ = c.printf("10.5: %.013a\n",
\\ @as(f64, 10.5)); \\ @as(f64, 10.5));
\\ _ = c.printf(c"10.5e5: %.013a\n", \\ _ = c.printf("10.5e5: %.013a\n",
\\ @as(f64, 10.5e5)); \\ @as(f64, 10.5e5));
\\ _ = c.printf(c"10.5e+5: %.013a\n", \\ _ = c.printf("10.5e+5: %.013a\n",
\\ @as(f64, 10.5e+5)); \\ @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)); \\ @as(f64, 50.0e-2));
\\ _ = c.printf(c"50e-2: %.013a\n", \\ _ = c.printf("50e-2: %.013a\n",
\\ @as(f64, 50e-2)); \\ @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)); \\ @as(f64, 0x1.0));
\\ _ = c.printf(c"0x10.0: %.013a\n", \\ _ = c.printf("0x10.0: %.013a\n",
\\ @as(f64, 0x10.0)); \\ @as(f64, 0x10.0));
\\ _ = c.printf(c"0x100.0: %.013a\n", \\ _ = c.printf("0x100.0: %.013a\n",
\\ @as(f64, 0x100.0)); \\ @as(f64, 0x100.0));
\\ _ = c.printf(c"0x103.0: %.013a\n", \\ _ = c.printf("0x103.0: %.013a\n",
\\ @as(f64, 0x103.0)); \\ @as(f64, 0x103.0));
\\ _ = c.printf(c"0x103.7: %.013a\n", \\ _ = c.printf("0x103.7: %.013a\n",
\\ @as(f64, 0x103.7)); \\ @as(f64, 0x103.7));
\\ _ = c.printf(c"0x103.70: %.013a\n", \\ _ = c.printf("0x103.70: %.013a\n",
\\ @as(f64, 0x103.70)); \\ @as(f64, 0x103.70));
\\ _ = c.printf(c"0x103.70p4: %.013a\n", \\ _ = c.printf("0x103.70p4: %.013a\n",
\\ @as(f64, 0x103.70p4)); \\ @as(f64, 0x103.70p4));
\\ _ = c.printf(c"0x103.70p5: %.013a\n", \\ _ = c.printf("0x103.70p5: %.013a\n",
\\ @as(f64, 0x103.70p5)); \\ @as(f64, 0x103.70p5));
\\ _ = c.printf(c"0x103.70p+5: %.013a\n", \\ _ = c.printf("0x103.70p+5: %.013a\n",
\\ @as(f64, 0x103.70p+5)); \\ @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)); \\ @as(f64, 0x103.70p-5));
\\ \\
\\ return 0; \\ return 0;
@ -323,7 +323,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
\\ const x: f64 = small; \\ const x: f64 = small;
\\ const y = @floatToInt(i32, x); \\ const y = @floatToInt(i32, x);
\\ const z = @intToFloat(f64, y); \\ 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; \\ return 0;
\\} \\}
, "3.25\n3\n3.00\n-0.40\n"); , "3.25\n3\n3.00\n-0.40\n");

View File

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

View File

@ -132,9 +132,16 @@ test "single-item pointer to array indexing and slicing" {
} }
fn testSingleItemPtrArrayIndexSlice() void { fn testSingleItemPtrArrayIndexSlice() void {
var array = "aaaa"; {
var array: [4]u8 = "aaaa".*;
doSomeMangling(&array); doSomeMangling(&array);
expect(mem.eql(u8, "azya", array)); expect(mem.eql(u8, "azya", &array));
}
{
var array = "aaaa".*;
doSomeMangling(&array);
expect(mem.eql(u8, "azya", &array));
}
} }
fn doSomeMangling(array: *[4]u8) void { 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" { test "implicit cast zero sized array ptr to slice" {
var b = ""; {
var b = "".*;
const c: []const u8 = &b; const c: []const u8 = &b;
expect(c.len == 0); expect(c.len == 0);
}
{
var b: [0]u8 = "".*;
const c: []const u8 = &b;
expect(c.len == 0);
}
} }
test "anonymous list literal syntax" { test "anonymous list literal syntax" {
@ -333,3 +347,16 @@ test "anonymous literal in array" {
S.doTheTest(); S.doTheTest();
comptime 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 { fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu"; {
var array = "aoeu".*;
const x: [*]u8 = &array; const x: [*]u8 = &array;
x[0] += 1; x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu")); 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" { test "peer type resolution: [0]u8, []const u8, and anyerror![]u8" {
const S = struct {
fn doTheTest() anyerror!void {
{ {
var data = "hi"; var data = "hi".*;
const slice = data[0..]; const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
} }
comptime { {
var data = "hi"; var data: [2]u8 = "hi".*;
const slice = data[0..]; const slice = data[0..];
expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0); expect((try peerTypeEmptyArrayAndSliceAndError(true, slice)).len == 0);
expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1); expect((try peerTypeEmptyArrayAndSliceAndError(false, slice)).len == 1);
} }
}
};
try S.doTheTest();
try comptime S.doTheTest();
} }
fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 { fn peerTypeEmptyArrayAndSliceAndError(a: bool, slice: []u8) anyerror![]u8 {
if (a) { if (a) {
@ -217,11 +223,20 @@ test "implicit cast from &const [N]T to []const T" {
} }
fn testCastConstArrayRefToConstSlice() void { fn testCastConstArrayRefToConstSlice() void {
const blah = "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; const const_array_ref = &blah;
expect(@typeOf(const_array_ref) == *const [4]u8); expect(@typeOf(const_array_ref) == *const [4]u8);
const slice: []const u8 = const_array_ref; const slice: []const u8 = const_array_ref;
expect(mem.eql(u8, slice, "aoeu")); expect(mem.eql(u8, slice, "aoeu"));
}
} }
test "peer type resolution: error and [N]T" { 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 { fn testCastPtrOfArrayToSliceAndPtr() void {
var array = "aoeu"; {
var array = "aoeu".*;
const x: [*]u8 = &array; const x: [*]u8 = &array;
x[0] += 1; x[0] += 1;
expect(mem.eql(u8, array[0..], "boeu")); expect(mem.eql(u8, array[0..], "boeu"));
const y: []u8 = &array; const y: []u8 = &array;
y[0] += 1; y[0] += 1;
expect(mem.eql(u8, array[0..], "coeu")); 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" { 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; const x: [*]const ?[*]const u8 = &window_name;
expect(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "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" { 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 buf: anyerror![]const u8 = buffer[0..];
var b = false; var b = false;
var y = if (b) &[0]u8{} else buf; 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" { 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 buf: []const u8 = buffer[0..];
var b = false; var b = false;
var y = if (b) &[0]u8{} else buf; 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); const f = @ptrCast(extern fn () void, &global_array);
expect(@ptrToInt(f) == @ptrToInt(&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" { test "const slice child" {
const strs = [_][*]const u8{ const strs = [_][*]const u8{
c"one", "one",
c"two", "two",
c"three", "three",
}; };
// TODO this should implicitly cast argv = &strs;
argv = @ptrCast([*]const [*]const u8, &strs);
bar(strs.len); bar(strs.len);
} }

View File

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

View File

@ -204,11 +204,11 @@ test "multiline string" {
test "multiline C string" { test "multiline C string" {
const s1 = const s1 =
c\\one \\one
c\\two) \\two)
c\\three \\three
; ;
const s2 = c"one\ntwo)\nthree"; const s2 = "one\ntwo)\nthree";
expect(std.cstr.cmp(s1, s2) == 0); 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; return a == b;
} }
test "C string concatenation" { test "string concatenation" {
const a = c"OK" ++ c" IT " ++ c"WORKED"; const a = "OK" ++ " IT " ++ "WORKED";
const b = c"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 = mem.len(u8, b);
const len_with_null = len + 1; const len_with_null = len + 1;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,7 +5,7 @@ const c = @cImport({
@cInclude("string.h"); @cInclude("string.h");
}); });
const msg = c"Hello, world!\n"; const msg = "Hello, world!\n";
export fn main(argc: c_int, argv: **u8) c_int { export fn main(argc: c_int, argv: **u8) c_int {
if (c.printf(msg) != @intCast(c_int, c.strlen(msg))) return -1; 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 { \\pub fn foo() void {
\\ var a: c_int = undefined; \\ var a: c_int = undefined;
\\ _ = 1; \\ _ = 1;
\\ _ = c"hey"; \\ _ = "hey";
\\ _ = (1 + 1); \\ _ = (1 + 1);
\\ _ = (1 - 1); \\ _ = (1 - 1);
\\ a = 1; \\ a = 1;
@ -213,9 +213,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
, ,
\\pub fn foo() void { \\pub fn foo() void {
\\ _ = c"foo"; \\ _ = "foo";
\\ _ = c"foo"; \\ _ = "foo";
\\ _ = c"void foo(void)"; \\ _ = "void foo(void)";
\\} \\}
); );
@ -232,7 +232,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\pub fn foo() void { \\pub fn foo() void {
\\ var a: c_int = undefined; \\ var a: c_int = undefined;
\\ _ = 1; \\ _ = 1;
\\ _ = c"hey"; \\ _ = "hey";
\\ _ = (1 + 1); \\ _ = (1 + 1);
\\ _ = (1 - 1); \\ _ = (1 - 1);
\\ a = 1; \\ a = 1;
@ -543,7 +543,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add("#define string", cases.add("#define string",
\\#define foo "a 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", 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 FOO2 "aoeu\x0007a derp"
\\#define FOO_CHAR '\xfF' \\#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; \\pub const FOO_CHAR = 255;
); );
@ -629,9 +629,9 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\#define FOO2 "aoeu\0234 derp" \\#define FOO2 "aoeu\0234 derp"
\\#define FOO_CHAR '\077' \\#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; \\pub const FOO_CHAR = 63;
); );
@ -1351,7 +1351,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
, ,
\\pub fn foo() [*c]const u8 { \\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", cases.add("const ptr initializer",
\\static const char *v0 = "0.0.0"; \\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", cases.add("static incomplete array inside function",
@ -1532,7 +1532,7 @@ pub fn addCases(cases: *tests.TranslateCContext) void {
\\} \\}
, ,
\\pub fn foo() 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 i: u8 = @as(u8, '\x0b');
\\ var j: u8 = @as(u8, '\x00'); \\ var j: u8 = @as(u8, '\x00');
\\ var k: u8 = @as(u8, '\"'); \\ var k: u8 = @as(u8, '\"');
\\ return c"\'\\\x07\x08\x0c\n\r\t\x0b\x00\""; \\ return "\'\\\x07\x08\x0c\n\r\t\x0b\x00\"";
\\} \\}
\\ \\
); );