Merge remote-tracking branch 'origin/master' into llvm10

master
Andrew Kelley 2020-03-22 15:09:29 -04:00
commit 23c263776c
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
29 changed files with 459 additions and 93 deletions

View File

@ -430,7 +430,6 @@ set(BUILD_LIBSTAGE2_ARGS "build-lib"
--cache on
--output-dir "${CMAKE_BINARY_DIR}"
${LIBSTAGE2_RELEASE_ARG}
--disable-gen-h
--bundle-compiler-rt
-fPIC
-lc

View File

@ -135,7 +135,8 @@ pub fn build(b: *Builder) !void {
test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
test_step.dependOn(tests.addTranslateCTests(b, test_filter));
test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter));
test_step.dependOn(tests.addGenHTests(b, test_filter));
// tests for this feature are disabled until we have the self-hosted compiler available
//test_step.dependOn(tests.addGenHTests(b, test_filter));
test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
test_step.dependOn(docs_step);
}

View File

@ -26,7 +26,8 @@ make -j$(nproc) install
# TODO test-cli is hitting https://github.com/ziglang/zig/issues/3526
./zig build test-asm-link test-runtime-safety
# TODO test-translate-c is hitting https://github.com/ziglang/zig/issues/3526
./zig build test-gen-h
# TODO disabled until we are shipping self-hosted
#./zig build test-gen-h
# TODO test-compile-errors is hitting https://github.com/ziglang/zig/issues/3526
# TODO building docs is hitting https://github.com/ziglang/zig/issues/3526

View File

@ -42,7 +42,8 @@ release/bin/zig build test-asm-link
release/bin/zig build test-runtime-safety
release/bin/zig build test-translate-c
release/bin/zig build test-run-translated-c
release/bin/zig build test-gen-h
# TODO disabled until we are shipping self-hosted
#release/bin/zig build test-gen-h
release/bin/zig build test-compile-errors
release/bin/zig build docs

View File

@ -193,6 +193,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
@ -514,6 +515,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
@ -697,6 +699,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
29
@ -819,6 +822,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
29
@ -904,6 +908,9 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
29
29
@ -1004,6 +1011,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
29
@ -1033,6 +1041,7 @@ aarch64-linux-gnu aarch64_be-linux-gnu
29
29
29
29
29
29
@ -3920,6 +3929,7 @@ s390x-linux-gnu
5
27
27
@ -4241,6 +4251,7 @@ s390x-linux-gnu
5
5
5
5
11
27
@ -4424,6 +4435,7 @@ s390x-linux-gnu
19
19
5
5
5
28
@ -4543,6 +4555,7 @@ s390x-linux-gnu
27
16
5
5
15
@ -4631,6 +4644,9 @@ s390x-linux-gnu
16
5
5
12
5
5
5
@ -4731,6 +4747,7 @@ s390x-linux-gnu
5
5
5
5
5
5
@ -4756,6 +4773,7 @@ s390x-linux-gnu
5
5
5
5
31 5
24 5 12 16
24 5 12 16
@ -7645,6 +7663,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
27
@ -7968,6 +7987,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
16
16
16
16
27
@ -8151,6 +8171,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
19
19
16
16
16
28
@ -8273,6 +8294,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
16
16
16
16
16
16
@ -8358,6 +8380,9 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
16
16
16
16
16
16
16
@ -8458,6 +8483,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
16
16
16
16
16
16
@ -8484,6 +8510,7 @@ arm-linux-gnueabi armeb-linux-gnueabi arm-linux-gnueabihf armeb-linux-gnueabihf
16
16
16
16
24 16
24 16
16
@ -11374,6 +11401,7 @@ sparc-linux-gnu sparcel-linux-gnu
0
27
27
@ -11693,6 +11721,7 @@ sparc-linux-gnu sparcel-linux-gnu
0
0
1
1
0
0
3 11
@ -11878,6 +11907,7 @@ sparc-linux-gnu sparcel-linux-gnu
19
19
0
0
1
28
@ -11997,6 +12027,7 @@ sparc-linux-gnu sparcel-linux-gnu
33
16
5
0
15
@ -12085,6 +12116,9 @@ sparc-linux-gnu sparcel-linux-gnu
16
0
0
12
1
1
1
@ -12183,6 +12217,7 @@ sparc-linux-gnu sparcel-linux-gnu
1
1
1
1
0
0
@ -12207,6 +12242,7 @@ sparc-linux-gnu sparcel-linux-gnu
0
0
0
0
5
0
0
@ -15101,6 +15137,7 @@ sparcv9-linux-gnu
5
5
27
27
@ -15422,6 +15459,7 @@ sparcv9-linux-gnu
5
5
5
5
11
27
@ -15605,6 +15643,7 @@ sparcv9-linux-gnu
19
19
5
5
5
28
@ -15724,6 +15763,7 @@ sparcv9-linux-gnu
27
16
5
5
15
@ -15812,6 +15852,9 @@ sparcv9-linux-gnu
16
5
5
12
5
5
5
@ -15912,6 +15955,7 @@ sparcv9-linux-gnu
5
5
5
5
5
5
@ -15938,6 +15982,7 @@ sparcv9-linux-gnu
5
5
5
5
24 28 5 12 16
24 28 5 12 16
5 14
@ -18828,6 +18873,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
0
27
27
@ -19147,6 +19193,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
0
0
5
5
0
0
11
@ -19332,6 +19379,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
19
19
0
0
5
28
@ -19450,6 +19498,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
27
27
16
16
5
0
@ -19539,6 +19588,9 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
16
0
0
12
5
5
5
@ -19637,6 +19689,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
5
5
5
5
0
0
0
@ -19661,6 +19714,7 @@ mips64el-linux-gnuabi64 mips64-linux-gnuabi64
0
0
0
0
5
0
0
@ -22555,6 +22609,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
0
27
27
@ -22874,6 +22929,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
0
0
5
5
0
0
11
@ -23059,6 +23115,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
19
19
0
0
5
28
@ -23177,6 +23234,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
27
27
16
16
5
0
@ -23266,6 +23324,9 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
16
0
0
12
5
5
5
@ -23364,6 +23425,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
5
5
5
5
0
0
0
@ -23388,6 +23450,7 @@ mips64el-linux-gnuabin32 mips64-linux-gnuabin32
0
0
0
0
5
0
0
@ -26282,6 +26345,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
0
27
27
@ -26601,6 +26665,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
0
0
5
5
0
0
11
@ -26786,6 +26851,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
19
19
0
0
5
28
@ -26904,6 +26970,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
27
16
16
5
0
@ -26993,6 +27060,9 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
16
0
0
12
5
5
5
@ -27091,6 +27161,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
5
5
5
5
0
0
0
@ -27115,6 +27186,7 @@ mipsel-linux-gnueabihf mips-linux-gnueabihf
0
0
0
0
5
0
0
@ -30009,6 +30081,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
0
27
27
@ -30328,6 +30401,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
0
0
5
5
0
0
11
@ -30513,6 +30587,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
19
19
0
0
5
28
@ -30631,6 +30706,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
27
16
16
5
0
@ -30720,6 +30796,9 @@ mipsel-linux-gnueabi mips-linux-gnueabi
16
0
0
12
5
5
5
@ -30818,6 +30897,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
5
5
5
5
0
0
0
@ -30842,6 +30922,7 @@ mipsel-linux-gnueabi mips-linux-gnueabi
0
0
0
0
5
0
0
@ -33734,6 +33815,7 @@ x86_64-linux-gnu
27
@ -34057,6 +34139,7 @@ x86_64-linux-gnu
10
10
10
10
11
27
36
@ -34240,6 +34323,7 @@ x86_64-linux-gnu
19
19
10
10
10
28
@ -34359,6 +34443,7 @@ x86_64-linux-gnu
27
16
10
10
15
@ -34447,6 +34532,9 @@ x86_64-linux-gnu
16
10
10
12
10
10
10
@ -34547,6 +34635,7 @@ x86_64-linux-gnu
10
10
10
10
10
10
@ -34573,6 +34662,7 @@ x86_64-linux-gnu
10
10
10
10
24 10 12 16
24 10 12 16
10 14
@ -37461,6 +37551,7 @@ x86_64-linux-gnux32
28
@ -37784,6 +37875,7 @@ x86_64-linux-gnux32
28
28
28
28
28
36
@ -37967,6 +38059,7 @@ x86_64-linux-gnux32
28
28
28
28
28
28
@ -38086,6 +38179,7 @@ x86_64-linux-gnux32
28
28
28
28
28
@ -38174,6 +38268,9 @@ x86_64-linux-gnux32
28
28
28
28
28
28
28
@ -38274,6 +38371,7 @@ x86_64-linux-gnux32
28
28
28
28
28
28
@ -38303,6 +38401,7 @@ x86_64-linux-gnux32
28
28
28
28
28
28
@ -41190,6 +41289,7 @@ i386-linux-gnu
0
12
27
36
27
@ -41509,6 +41609,7 @@ i386-linux-gnu
0
0
1
1
0
0
3 11
@ -41694,6 +41795,7 @@ i386-linux-gnu
19
19
0
0
1
28
@ -41813,6 +41915,7 @@ i386-linux-gnu
27
16
5
0
15
@ -41901,6 +42004,9 @@ i386-linux-gnu
16
0
0
12
1
1
1
@ -41999,6 +42105,7 @@ i386-linux-gnu
1
1
1
1
0
0
@ -42023,6 +42130,7 @@ i386-linux-gnu
0
0
0
0
5
0
0
@ -44915,6 +45023,7 @@ powerpc64le-linux-gnu
29
@ -45238,6 +45347,7 @@ powerpc64le-linux-gnu
29
29
29
29
29
36
@ -45421,6 +45531,7 @@ powerpc64le-linux-gnu
29
29
29
33
29
29
29
@ -45540,6 +45651,7 @@ powerpc64le-linux-gnu
29
29
29
29
29
@ -45628,6 +45740,9 @@ powerpc64le-linux-gnu
29
29
29
29
32
29
29
29
@ -45728,6 +45843,7 @@ powerpc64le-linux-gnu
29
29
29
29
29
29
@ -45757,6 +45873,7 @@ powerpc64le-linux-gnu
29
29
29
29
29
29
@ -48642,6 +48759,7 @@ powerpc64-linux-gnu
27
@ -48965,6 +49083,7 @@ powerpc64-linux-gnu
12
12
12
12
27
@ -49148,6 +49267,7 @@ powerpc64-linux-gnu
19
19
12
33
12
12
28
@ -49267,6 +49387,7 @@ powerpc64-linux-gnu
27
16
12
12
15
@ -49355,6 +49476,9 @@ powerpc64-linux-gnu
16
12
12
12
32
12
12
12
@ -49455,6 +49579,7 @@ powerpc64-linux-gnu
12
12
12
12
12
12
@ -49480,6 +49605,7 @@ powerpc64-linux-gnu
12
12
12
12
12 15
24 12 16
24 12 16
@ -52369,6 +52495,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
27
@ -52690,6 +52817,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
0
0
1
1
0
0
3 11
@ -52875,6 +53003,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
19
19
0
33
0
1
28
@ -52994,6 +53123,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
27
13
16
5
0
15
@ -53082,6 +53212,9 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
16
0
0
12
32
1
1
1
@ -53180,6 +53313,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
1
1
1
1
0
0
@ -53204,6 +53338,7 @@ powerpc-linux-gnueabi powerpc-linux-gnueabihf
0
0
0
0
5
0
0

View File

@ -192,6 +192,7 @@ _Qp_uitoq c
_Qp_uxtoq c
_Qp_xtoq c
___brk_addr c
___tls_get_addr ld
__acos_finite m
__acosf128_finite m
__acosf_finite m
@ -511,6 +512,7 @@ __libc_memalign c
__libc_pvalloc c
__libc_realloc c
__libc_sa_len c
__libc_stack_end ld
__libc_start_main c
__libc_valloc c
__libpthread_version_placeholder pthread
@ -696,6 +698,7 @@ __open_2 c
__openat64_2 c
__openat_2 c
__overflow c
__parse_hwcap_and_convert_at_platform ld
__pipe c
__poll c
__poll_chk c
@ -815,6 +818,7 @@ __sqrtf_finite m
__sqrtl_finite m
__sqrtsf2 c
__stack_chk_fail c
__stack_chk_guard ld
__statfs c
__stpcpy c
__stpcpy_chk c
@ -903,6 +907,9 @@ __sysctl c
__syslog_chk c
__sysv_signal c
__timezone c
__tls_get_addr ld
__tls_get_addr_opt ld
__tls_get_offset ld
__toascii_l c
__tolower_l c
__toupper_l c
@ -999,6 +1006,7 @@ __ynf128_finite m
__ynf_finite m
__ynl_finite m
_authenticate c
_dl_mcount ld
_dl_mcount_wrapper c
_dl_mcount_wrapper_check c
_environ c
@ -1024,6 +1032,7 @@ _pthread_cleanup_pop pthread
_pthread_cleanup_pop_restore pthread
_pthread_cleanup_push pthread
_pthread_cleanup_push_defer pthread
_r_debug ld
_res c
_res_hconf c
_rpc_dtablesize c

View File

@ -1121,7 +1121,7 @@ pub const LibExeObjStep = struct {
emit_llvm_ir: bool = false,
emit_asm: bool = false,
emit_bin: bool = true,
disable_gen_h: bool,
emit_h: bool = false,
bundle_compiler_rt: bool,
disable_stack_probing: bool,
disable_sanitize_c: bool,
@ -1281,7 +1281,6 @@ pub const LibExeObjStep = struct {
.exec_cmd_args = null,
.name_prefix = "",
.filter = null,
.disable_gen_h = false,
.bundle_compiler_rt = false,
.disable_stack_probing = false,
.disable_sanitize_c = false,
@ -1600,8 +1599,9 @@ pub const LibExeObjStep = struct {
self.main_pkg_path = dir_path;
}
pub fn setDisableGenH(self: *LibExeObjStep, value: bool) void {
self.disable_gen_h = value;
/// Deprecated; just set the field directly.
pub fn setDisableGenH(self: *LibExeObjStep, is_disabled: bool) void {
self.emit_h = !is_disabled;
}
pub fn setLibCFile(self: *LibExeObjStep, libc_file: ?[]const u8) void {
@ -1632,7 +1632,7 @@ pub const LibExeObjStep = struct {
/// the make step, from a step that has declared a dependency on this one.
pub fn getOutputHPath(self: *LibExeObjStep) []const u8 {
assert(self.kind != Kind.Exe);
assert(!self.disable_gen_h);
assert(self.emit_h);
return fs.path.join(
self.builder.allocator,
&[_][]const u8{ self.output_dir.?, self.out_h_filename },
@ -1679,7 +1679,7 @@ pub const LibExeObjStep = struct {
}
pub fn addBuildOption(self: *LibExeObjStep, comptime T: type, name: []const u8, value: T) void {
const out = &std.io.BufferOutStream.init(&self.build_options_contents).stream;
const out = self.build_options_contents.outStream();
out.print("pub const {} = {};\n", .{ name, value }) catch unreachable;
}
@ -1884,6 +1884,7 @@ pub const LibExeObjStep = struct {
if (self.emit_llvm_ir) try zig_args.append("-femit-llvm-ir");
if (self.emit_asm) try zig_args.append("-femit-asm");
if (!self.emit_bin) try zig_args.append("-fno-emit-bin");
if (self.emit_h) try zig_args.append("-femit-h");
if (self.strip) {
try zig_args.append("--strip");
@ -1929,9 +1930,6 @@ pub const LibExeObjStep = struct {
if (self.is_dynamic) {
try zig_args.append("-dynamic");
}
if (self.disable_gen_h) {
try zig_args.append("--disable-gen-h");
}
if (self.bundle_compiler_rt) {
try zig_args.append("--bundle-compiler-rt");
}
@ -2069,7 +2067,7 @@ pub const LibExeObjStep = struct {
try zig_args.append("-isystem");
try zig_args.append(self.builder.pathFromRoot(include_path));
},
.OtherStep => |other| if (!other.disable_gen_h) {
.OtherStep => |other| if (other.emit_h) {
const h_path = other.getOutputHPath();
try zig_args.append("-isystem");
try zig_args.append(fs.path.dirname(h_path).?);
@ -2209,7 +2207,7 @@ const InstallArtifactStep = struct {
break :blk InstallDir.Lib;
}
} else null,
.h_dir = if (artifact.kind == .Lib and !artifact.disable_gen_h) .Header else null,
.h_dir = if (artifact.kind == .Lib and artifact.emit_h) .Header else null,
};
self.step.dependOn(&artifact.step);
artifact.install_step = self;

View File

@ -235,9 +235,17 @@ pub fn panic(comptime format: []const u8, args: var) noreturn {
panicExtra(null, first_trace_addr, format, args);
}
/// TODO multithreaded awareness
/// Non-zero whenever the program triggered a panic.
/// The counter is incremented/decremented atomically.
var panicking: u8 = 0;
// Locked to avoid interleaving panic messages from multiple threads.
var panic_mutex = std.Mutex.init();
/// Counts how many times the panic handler is invoked by this thread.
/// This is used to catch and handle panics triggered by the panic handler.
threadlocal var panic_stage: usize = 0;
pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, comptime format: []const u8, args: var) noreturn {
@setCold(true);
@ -247,25 +255,50 @@ pub fn panicExtra(trace: ?*const builtin.StackTrace, first_trace_addr: ?usize, c
resetSegfaultHandler();
}
switch (@atomicRmw(u8, &panicking, .Add, 1, .SeqCst)) {
switch (panic_stage) {
0 => {
const stderr = getStderrStream();
noasync stderr.print(format ++ "\n", args) catch os.abort();
if (trace) |t| {
dumpStackTrace(t.*);
panic_stage = 1;
_ = @atomicRmw(u8, &panicking, .Add, 1, .SeqCst);
// Make sure to release the mutex when done
{
const held = panic_mutex.acquire();
defer held.release();
const stderr = getStderrStream();
noasync stderr.print(format ++ "\n", args) catch os.abort();
if (trace) |t| {
dumpStackTrace(t.*);
}
dumpCurrentStackTrace(first_trace_addr);
}
if (@atomicRmw(u8, &panicking, .Sub, 1, .SeqCst) != 1) {
// Another thread is panicking, wait for the last one to finish
// and call abort()
// Sleep forever without hammering the CPU
var event = std.ResetEvent.init();
event.wait();
unreachable;
}
dumpCurrentStackTrace(first_trace_addr);
},
1 => {
// TODO detect if a different thread caused the panic, because in that case
// we would want to return here instead of calling abort, so that the thread
// which first called panic can finish printing a stack trace.
warn("Panicked during a panic. Aborting.\n", .{});
panic_stage = 2;
// A panic happened while trying to print a previous panic message,
// we're still holding the mutex but that's fine as we're going to
// call abort()
const stderr = getStderrStream();
noasync stderr.print("Panicked during a panic. Aborting.\n", .{}) catch os.abort();
},
else => {
// Panicked while printing "Panicked during a panic."
},
}
os.abort();
}

View File

@ -820,7 +820,7 @@ fn linuxLookupNameFromHosts(
// Skip to the delimiter in the stream, to fix parsing
try stream.skipUntilDelimiterOrEof('\n');
// Use the truncated line. A truncated comment or hostname will be handled correctly.
break :blk @as([]u8, &line_buf); // TODO the cast should not be necessary
break :blk &line_buf;
},
else => |e| return e,
}) |line| {
@ -1017,7 +1017,7 @@ fn getResolvConf(allocator: *mem.Allocator, rc: *ResolvConf) !void {
// Skip to the delimiter in the stream, to fix parsing
try stream.skipUntilDelimiterOrEof('\n');
// Give an empty line to the while loop, which will be skipped.
break :blk @as([]u8, line_buf[0..0]); // TODO the cast should not be necessary
break :blk line_buf[0..0];
},
else => |e| return e,
}) |line| {

View File

@ -41,6 +41,10 @@ fn _DllMainCRTStartup(
fdwReason: std.os.windows.DWORD,
lpReserved: std.os.windows.LPVOID,
) callconv(.Stdcall) std.os.windows.BOOL {
if (!builtin.single_threaded) {
_ = @import("start_windows_tls.zig");
}
if (@hasDecl(root, "DllMain")) {
return root.DllMain(hinstDLL, fdwReason, lpReserved);
}

View File

@ -1035,6 +1035,7 @@ pub const Node = struct {
pub const Defer = struct {
base: Node = Node{ .id = .Defer },
defer_token: TokenIndex,
payload: ?*Node,
expr: *Node,
pub fn iterate(self: *Defer, index: usize) ?*Node {
@ -1836,8 +1837,7 @@ pub const Node = struct {
var i = index;
switch (self.kind) {
.Break,
.Continue => |maybe_label| {
.Break, .Continue => |maybe_label| {
if (maybe_label) |label| {
if (i < 1) return label;
i -= 1;
@ -1864,8 +1864,7 @@ pub const Node = struct {
}
switch (self.kind) {
.Break,
.Continue => |maybe_label| {
.Break, .Continue => |maybe_label| {
if (maybe_label) |label| {
return label.lastToken();
}

View File

@ -465,7 +465,7 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
/// / KEYWORD_noasync BlockExprStatement
/// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
/// / KEYWORD_defer BlockExprStatement
/// / KEYWORD_errdefer BlockExprStatement
/// / KEYWORD_errdefer Payload? BlockExprStatement
/// / IfStatement
/// / LabeledStatement
/// / SwitchExpr
@ -526,6 +526,10 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
const defer_token = eatToken(it, .Keyword_defer) orelse eatToken(it, .Keyword_errdefer);
if (defer_token) |token| {
const payload = if (tree.tokens.at(token).id == .Keyword_errdefer)
try parsePayload(arena, it, tree)
else
null;
const expr_node = try expectNode(arena, it, tree, parseBlockExprStatement, .{
.ExpectedBlockOrExpression = .{ .token = it.index },
});
@ -533,6 +537,7 @@ fn parseStatement(arena: *Allocator, it: *TokenIterator, tree: *Tree) Error!?*No
node.* = .{
.defer_token = token,
.expr = expr_node,
.payload = payload,
};
return &node.base;
}

View File

@ -1,3 +1,16 @@
test "zig fmt: errdefer with payload" {
try testCanonical(
\\pub fn main() anyerror!void {
\\ errdefer |a| x += 1;
\\ errdefer |a| {}
\\ errdefer |a| {
\\ x += 1;
\\ }
\\}
\\
);
}
test "zig fmt: noasync block" {
try testCanonical(
\\pub fn main() anyerror!void {

View File

@ -376,6 +376,9 @@ fn renderExpression(
const defer_node = @fieldParentPtr(ast.Node.Defer, "base", base);
try renderToken(tree, stream, defer_node.defer_token, indent, start_col, Space.Space);
if (defer_node.payload) |payload| {
try renderExpression(allocator, stream, tree, indent, start_col, payload, Space.Space);
}
return renderExpression(allocator, stream, tree, indent, start_col, defer_node.expr, space);
},
.Comptime => {

View File

@ -909,6 +909,7 @@ const Stage2Target = extern struct {
os_builtin_str: ?[*:0]const u8,
dynamic_linker: ?[*:0]const u8,
standard_dynamic_linker_path: ?[*:0]const u8,
fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
const allocator = std.heap.c_allocator;
@ -1119,6 +1120,12 @@ const Stage2Target = extern struct {
}
};
const std_dl = target.standardDynamicLinkerPath();
const std_dl_z = if (std_dl.get()) |dl|
(try mem.dupeZ(std.heap.c_allocator, u8, dl)).ptr
else
null;
const cache_hash_slice = cache_hash.toOwnedSlice();
self.* = .{
.arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
@ -1134,6 +1141,7 @@ const Stage2Target = extern struct {
.is_native = cross_target.isNative(),
.glibc_or_darwin_version = glibc_or_darwin_version,
.dynamic_linker = dynamic_linker,
.standard_dynamic_linker_path = std_dl_z,
};
}
};

View File

@ -744,6 +744,7 @@ struct AstNodeReturnExpr {
struct AstNodeDefer {
ReturnKind kind;
AstNode *err_payload;
AstNode *expr;
// temporary data used in IR generation
@ -2266,6 +2267,7 @@ struct CodeGen {
Buf *zig_lib_dir;
Buf *zig_std_dir;
Buf *version_script_path;
Buf *override_soname;
const char **llvm_argv;
size_t llvm_argv_len;

View File

@ -10504,6 +10504,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_str(ch, g->libc->kernel32_lib_dir);
}
cache_buf_opt(ch, g->version_script_path);
cache_buf_opt(ch, g->override_soname);
// gen_c_objects appends objects to g->link_objects which we want to include in the hash
gen_c_objects(g);

View File

@ -16,6 +16,7 @@ static const ZigGLibCLib glibc_libs[] = {
{"pthread", 0},
{"dl", 2},
{"rt", 1},
{"ld", 2},
};
Error glibc_load_metadata(ZigGLibCAbi **out_result, Buf *zig_lib_dir, bool verbose) {
@ -330,6 +331,8 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
return err;
}
bool is_ld = (strcmp(lib->name, "ld") == 0);
CodeGen *child_gen = create_child_codegen(g, zig_file_path, OutTypeLib, nullptr, lib->name, progress_node);
codegen_set_lib_version(child_gen, lib->sover, 0, 0);
child_gen->is_dynamic = true;
@ -337,6 +340,13 @@ Error glibc_build_dummies_and_maps(CodeGen *g, const ZigGLibCAbi *glibc_abi, con
child_gen->version_script_path = map_file_path;
child_gen->enable_cache = false;
child_gen->output_dir = dummy_dir;
if (is_ld) {
assert(g->zig_target->standard_dynamic_linker_path != nullptr);
Buf *ld_basename = buf_alloc();
os_path_split(buf_create_from_str(g->zig_target->standard_dynamic_linker_path),
nullptr, ld_basename);
child_gen->override_soname = ld_basename;
}
codegen_build_and_link(child_gen);
}

View File

@ -272,6 +272,10 @@ static ResultLoc *no_result_loc(void);
static IrInstGen *ir_analyze_test_non_null(IrAnalyze *ira, IrInst *source_inst, IrInstGen *value);
static IrInstGen *ir_error_dependency_loop(IrAnalyze *ira, IrInst *source_instr);
static IrInstGen *ir_const_undef(IrAnalyze *ira, IrInst *source_instruction, ZigType *ty);
static ZigVar *ir_create_var(IrBuilderSrc *irb, AstNode *node, Scope *scope, Buf *name,
bool src_is_const, bool gen_is_const, bool is_shadowable, IrInstSrc *is_comptime);
static void build_decl_var_and_init(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, ZigVar *var,
IrInstSrc *init, const char *name_hint, IrInstSrc *is_comptime);
static void destroy_instruction_src(IrInstSrc *inst) {
switch (inst->id) {
@ -5011,39 +5015,73 @@ static IrInstSrc *ir_mark_gen(IrInstSrc *instruction) {
return instruction;
}
static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool gen_error_defers) {
static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, bool *is_noreturn, IrInstSrc *err_value) {
Scope *scope = inner_scope;
bool is_noreturn = false;
if (is_noreturn != nullptr) *is_noreturn = false;
while (scope != outer_scope) {
if (!scope)
return is_noreturn;
return true;
switch (scope->id) {
case ScopeIdDefer: {
AstNode *defer_node = scope->source_node;
assert(defer_node->type == NodeTypeDefer);
ReturnKind defer_kind = defer_node->data.defer.kind;
if (defer_kind == ReturnKindUnconditional ||
(gen_error_defers && defer_kind == ReturnKindError))
{
AstNode *defer_expr_node = defer_node->data.defer.expr;
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
if (defer_expr_value != irb->codegen->invalid_inst_src) {
if (defer_expr_value->is_noreturn) {
is_noreturn = true;
} else {
ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
defer_expr_value));
}
AstNode *defer_expr_node = defer_node->data.defer.expr;
AstNode *defer_var_node = defer_node->data.defer.err_payload;
if (defer_kind == ReturnKindError && err_value == nullptr) {
// This is an `errdefer` but we're generating code for a
// `return` that doesn't return an error, skip it
scope = scope->parent;
continue;
}
Scope *defer_expr_scope = defer_node->data.defer.expr_scope;
if (defer_var_node != nullptr) {
assert(defer_kind == ReturnKindError);
assert(defer_var_node->type == NodeTypeSymbol);
Buf *var_name = defer_var_node->data.symbol_expr.symbol;
if (defer_expr_node->type == NodeTypeUnreachable) {
add_node_error(irb->codegen, defer_var_node,
buf_sprintf("unused variable: '%s'", buf_ptr(var_name)));
return false;
}
IrInstSrc *is_comptime;
if (ir_should_inline(irb->exec, defer_expr_scope)) {
is_comptime = ir_build_const_bool(irb, defer_expr_scope,
defer_expr_node, true);
} else {
is_comptime = ir_build_test_comptime(irb, defer_expr_scope,
defer_expr_node, err_value);
}
ZigVar *err_var = ir_create_var(irb, defer_var_node, defer_expr_scope,
var_name, true, true, false, is_comptime);
build_decl_var_and_init(irb, defer_expr_scope, defer_var_node, err_var, err_value,
buf_ptr(var_name), is_comptime);
defer_expr_scope = err_var->child_scope;
}
IrInstSrc *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope);
if (defer_expr_value == irb->codegen->invalid_inst_src)
return irb->codegen->invalid_inst_src;
if (defer_expr_value->is_noreturn) {
if (is_noreturn != nullptr) *is_noreturn = true;
} else {
ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node,
defer_expr_value));
}
scope = scope->parent;
continue;
}
case ScopeIdDecls:
case ScopeIdFnDef:
return is_noreturn;
return true;
case ScopeIdBlock:
case ScopeIdVarDecl:
case ScopeIdLoop:
@ -5060,7 +5098,7 @@ static bool ir_gen_defers_for_block(IrBuilderSrc *irb, Scope *inner_scope, Scope
zig_unreachable();
}
}
return is_noreturn;
return true;
}
static void ir_set_cursor_at_end_gen(IrBuilderGen *irb, IrBasicBlockGen *basic_block) {
@ -5146,7 +5184,8 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
bool have_err_defers = defer_counts[ReturnKindError] > 0;
if (!have_err_defers && !irb->codegen->have_err_ret_tracing) {
// only generate unconditional defers
ir_gen_defers_for_block(irb, scope, outer_scope, false);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
IrInstSrc *result = ir_build_return_src(irb, scope, node, nullptr);
result_loc_ret->base.source_instruction = result;
return result;
@ -5169,14 +5208,16 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
IrBasicBlockSrc *ret_stmt_block = ir_create_basic_block(irb, scope, "RetStmt");
ir_set_cursor_at_end_and_append_block(irb, err_block);
ir_gen_defers_for_block(irb, scope, outer_scope, true);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, return_value))
return irb->codegen->invalid_inst_src;
if (irb->codegen->have_err_ret_tracing && !should_inline) {
ir_build_save_err_ret_addr_src(irb, scope, node);
}
ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ok_block);
ir_gen_defers_for_block(irb, scope, outer_scope, false);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
ir_build_br(irb, scope, node, ret_stmt_block, is_comptime);
ir_set_cursor_at_end_and_append_block(irb, ret_stmt_block);
@ -5213,7 +5254,12 @@ static IrInstSrc *ir_gen_return(IrBuilderSrc *irb, Scope *scope, AstNode *node,
result_loc_ret->base.id = ResultLocIdReturn;
ir_build_reset_result(irb, scope, node, &result_loc_ret->base);
ir_build_end_expr(irb, scope, node, err_val, &result_loc_ret->base);
if (!ir_gen_defers_for_block(irb, scope, outer_scope, true)) {
bool is_noreturn = false;
if (!ir_gen_defers_for_block(irb, scope, outer_scope, &is_noreturn, err_val)) {
return irb->codegen->invalid_inst_src;
}
if (!is_noreturn) {
if (irb->codegen->have_err_ret_tracing && !should_inline) {
ir_build_save_err_ret_addr_src(irb, scope, node);
}
@ -5415,7 +5461,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
bool is_return_from_fn = block_node == irb->main_block_node;
if (!is_return_from_fn) {
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
}
IrInstSrc *result;
@ -5440,7 +5487,8 @@ static IrInstSrc *ir_gen_block(IrBuilderSrc *irb, Scope *parent_scope, AstNode *
result_loc_ret->base.id = ResultLocIdReturn;
ir_build_reset_result(irb, parent_scope, block_node, &result_loc_ret->base);
ir_mark_gen(ir_build_end_expr(irb, parent_scope, block_node, result, &result_loc_ret->base));
ir_gen_defers_for_block(irb, child_scope, outer_block_scope, false);
if (!ir_gen_defers_for_block(irb, child_scope, outer_block_scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
return ir_mark_gen(ir_build_return_src(irb, child_scope, result->base.source_node, result));
}
@ -9207,7 +9255,8 @@ static IrInstSrc *ir_gen_return_from_block(IrBuilderSrc *irb, Scope *break_scope
}
IrBasicBlockSrc *dest_block = block_scope->end_block;
ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
block_scope->incoming_blocks->append(irb->current_basic_block);
block_scope->incoming_values->append(result_value);
@ -9281,7 +9330,8 @@ static IrInstSrc *ir_gen_break(IrBuilderSrc *irb, Scope *break_scope, AstNode *n
}
IrBasicBlockSrc *dest_block = loop_scope->break_block;
ir_gen_defers_for_block(irb, break_scope, dest_block->scope, false);
if (!ir_gen_defers_for_block(irb, break_scope, dest_block->scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
loop_scope->incoming_blocks->append(irb->current_basic_block);
loop_scope->incoming_values->append(result_value);
@ -9340,7 +9390,8 @@ static IrInstSrc *ir_gen_continue(IrBuilderSrc *irb, Scope *continue_scope, AstN
}
IrBasicBlockSrc *dest_block = loop_scope->continue_block;
ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, false);
if (!ir_gen_defers_for_block(irb, continue_scope, dest_block->scope, nullptr, nullptr))
return irb->codegen->invalid_inst_src;
return ir_mark_gen(ir_build_br(irb, continue_scope, node, dest_block, is_comptime));
}
@ -12317,11 +12368,22 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
prev_type->data.pointer.child_type->id == ZigTypeIdArray &&
prev_type->data.pointer.ptr_len == PtrLenSingle &&
((cur_type->id == ZigTypeIdErrorUnion && is_slice(cur_type->data.error_union.payload_type)) ||
is_slice(cur_type)))
(cur_type->id == ZigTypeIdOptional && is_slice(cur_type->data.maybe.child_type)) ||
is_slice(cur_type)))
{
ZigType *array_type = prev_type->data.pointer.child_type;
ZigType *slice_type = (cur_type->id == ZigTypeIdErrorUnion) ?
cur_type->data.error_union.payload_type : cur_type;
ZigType *slice_type;
switch (cur_type->id) {
case ZigTypeIdErrorUnion:
slice_type = cur_type->data.error_union.payload_type;
break;
case ZigTypeIdOptional:
slice_type = cur_type->data.maybe.child_type;
break;
default:
slice_type = cur_type;
break;
}
ZigType *slice_ptr_type = slice_type->data.structure.fields[slice_ptr_index]->type_entry;
if ((slice_ptr_type->data.pointer.is_const || array_type->data.array.len == 0 ||
!prev_type->data.pointer.is_const) &&
@ -16191,6 +16253,15 @@ static IrInstGen *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstSrcBinOp *bin_op_i
IrInstGen *union_val = op1->value->type->id == ZigTypeIdUnion ? op1 : op2;
IrInstGen *enum_val = op1->value->type->id == ZigTypeIdUnion ? op2 : op1;
if (!is_tagged_union(union_val->value->type)) {
ErrorMsg *msg = ir_add_error_node(ira, source_node,
buf_sprintf("comparison of union and enum literal is only valid for tagged union types"));
add_error_note(ira->codegen, msg, union_val->value->type->data.unionation.decl_node,
buf_sprintf("type %s is not a tagged union",
buf_ptr(&union_val->value->type->name)));
return ira->codegen->invalid_inst_gen;
}
ZigType *tag_type = union_val->value->type->data.unionation.tag_type;
assert(tag_type != nullptr);

View File

@ -1651,7 +1651,6 @@ static void construct_linker_job_elf(LinkJob *lj) {
bool is_lib = g->out_type == OutTypeLib;
bool is_dyn_lib = g->is_dynamic && is_lib;
Buf *soname = nullptr;
if (!g->have_dynamic_link) {
if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
@ -1662,15 +1661,13 @@ static void construct_linker_job_elf(LinkJob *lj) {
}
} else if (is_dyn_lib) {
lj->args.append("-shared");
assert(buf_len(&g->bin_file_output_path) != 0);
soname = buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major);
}
if (target_requires_pie(g->zig_target) && g->out_type == OutTypeExe) {
lj->args.append("-pie");
}
assert(buf_len(&g->bin_file_output_path) != 0);
lj->args.append("-o");
lj->args.append(buf_ptr(&g->bin_file_output_path));
@ -1740,6 +1737,9 @@ static void construct_linker_job_elf(LinkJob *lj) {
}
if (is_dyn_lib) {
Buf *soname = (g->override_soname == nullptr) ?
buf_sprintf("lib%s.so.%" ZIG_PRI_usize, buf_ptr(g->root_out_name), g->version_major) :
g->override_soname;
lj->args.append("-soname");
lj->args.append(buf_ptr(soname));

View File

@ -54,7 +54,6 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" --cache-dir [path] override the local cache directory\n"
" --cache [auto|off|on] build in cache, print output path to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --disable-gen-h do not generate a C header file (.h)\n"
" --disable-valgrind omit valgrind client requests in debug builds\n"
" --eh-frame-hdr enable C++ exception handling by passing --eh-frame-hdr to linker\n"
" --enable-valgrind include valgrind client requests release builds\n"
@ -77,6 +76,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
" -fno-emit-asm (default) do not output .s (assembly code)\n"
" -femit-llvm-ir produce a .ll file with LLVM IR\n"
" -fno-emit-llvm-ir (default) do not produce a .ll file with LLVM IR\n"
" -femit-h generate a C header file (.h)\n"
" -fno-emit-h (default) do not generate a C header file (.h)\n"
" --libc [file] Provide a file which specifies libc paths\n"
" --name [name] override output name\n"
" --output-dir [dir] override output directory (defaults to cwd)\n"
@ -432,6 +433,7 @@ static int main0(int argc, char **argv) {
bool emit_bin = true;
bool emit_asm = false;
bool emit_llvm_ir = false;
bool emit_h = false;
const char *cache_dir = nullptr;
CliPkg *cur_pkg = heap::c_allocator.create<CliPkg>();
BuildMode build_mode = BuildModeDebug;
@ -440,7 +442,6 @@ static int main0(int argc, char **argv) {
bool system_linker_hack = false;
TargetSubsystem subsystem = TargetSubsystemAuto;
bool want_single_threaded = false;
bool disable_gen_h = false;
bool bundle_compiler_rt = false;
Buf *override_lib_dir = nullptr;
Buf *main_pkg_path = nullptr;
@ -661,9 +662,7 @@ static int main0(int argc, char **argv) {
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
} else if (strcmp(arg, "--single-threaded") == 0) {
want_single_threaded = true;
} else if (strcmp(arg, "--disable-gen-h") == 0) {
disable_gen_h = true;
want_single_threaded = true;;
} else if (strcmp(arg, "--bundle-compiler-rt") == 0) {
bundle_compiler_rt = true;
} else if (strcmp(arg, "--test-cmd-bin") == 0) {
@ -720,6 +719,11 @@ static int main0(int argc, char **argv) {
emit_llvm_ir = true;
} else if (strcmp(arg, "-fno-emit-llvm-ir") == 0) {
emit_llvm_ir = false;
} else if (strcmp(arg, "-femit-h") == 0) {
emit_h = true;
} else if (strcmp(arg, "-fno-emit-h") == 0 || strcmp(arg, "--disable-gen-h") == 0) {
// the --disable-gen-h is there to support godbolt. once they upgrade to -fno-emit-h then we can remove this
emit_h = false;
} else if (str_starts_with(arg, "-mcpu=")) {
mcpu = arg + strlen("-mcpu=");
} else if (i + 1 >= argc) {
@ -1203,7 +1207,7 @@ static int main0(int argc, char **argv) {
g->verbose_cc = verbose_cc;
g->verbose_llvm_cpu_features = verbose_llvm_cpu_features;
g->output_dir = output_dir;
g->disable_gen_h = disable_gen_h;
g->disable_gen_h = !emit_h;
g->bundle_compiler_rt = bundle_compiler_rt;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;

View File

@ -879,7 +879,7 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
// / KEYWORD_noasync BlockExprStatement
// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
// / KEYWORD_defer BlockExprStatement
// / KEYWORD_errdefer BlockExprStatement
// / KEYWORD_errdefer Payload? BlockExprStatement
// / IfStatement
// / LabeledStatement
// / SwitchExpr
@ -923,12 +923,18 @@ static AstNode *ast_parse_statement(ParseContext *pc) {
if (defer == nullptr)
defer = eat_token_if(pc, TokenIdKeywordErrdefer);
if (defer != nullptr) {
Token *payload = (defer->id == TokenIdKeywordErrdefer) ?
ast_parse_payload(pc) : nullptr;
AstNode *statement = ast_expect(pc, ast_parse_block_expr_statement);
AstNode *res = ast_create_node(pc, NodeTypeDefer, defer);
res->data.defer.kind = ReturnKindUnconditional;
res->data.defer.expr = statement;
if (defer->id == TokenIdKeywordErrdefer)
if (defer->id == TokenIdKeywordErrdefer) {
res->data.defer.kind = ReturnKindError;
if (payload != nullptr)
res->data.defer.err_payload = token_symbol(pc, payload);
}
return res;
}
@ -3032,6 +3038,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
break;
case NodeTypeDefer:
visit_field(&node->data.defer.expr, visit, context);
visit_field(&node->data.defer.err_payload, visit, context);
break;
case NodeTypeVariableDeclaration:
visit_field(&node->data.variable_declaration.type, visit, context);

View File

@ -291,6 +291,7 @@ struct ZigTarget {
size_t cache_hash_len;
const char *os_builtin_str;
const char *dynamic_linker;
const char *standard_dynamic_linker_path;
};
// ABI warning

View File

@ -2,6 +2,29 @@ const tests = @import("tests.zig");
const std = @import("std");
pub fn addCases(cases: *tests.CompileErrorContext) void {
cases.addTest("unused variable error on errdefer",
\\fn foo() !void {
\\ errdefer |a| unreachable;
\\ return error.A;
\\}
\\export fn entry() void {
\\ foo() catch unreachable;
\\}
, &[_][]const u8{
"tmp.zig:2:15: error: unused variable: 'a'",
});
cases.addTest("comparison of non-tagged union and enum literal",
\\export fn entry() void {
\\ const U = union { A: u32, B: u64 };
\\ var u = U{ .A = 42 };
\\ var ok = u == .A;
\\}
, &[_][]const u8{
"tmp.zig:4:16: error: comparison of union and enum literal is only valid for tagged union types",
"tmp.zig:2:15: note: type U is not a tagged union",
});
cases.addTest("shift on type with non-power-of-two size",
\\export fn entry() void {
\\ const S = struct {

View File

@ -1,4 +1,7 @@
const expect = @import("std").testing.expect;
const std = @import("std");
const expect = std.testing.expect;
const expectEqual = std.testing.expectEqual;
const expectError = std.testing.expectError;
var result: [3]u8 = undefined;
var index: usize = undefined;
@ -93,3 +96,19 @@ test "return variable while defer expression in scope to modify it" {
S.doTheTest();
comptime S.doTheTest();
}
test "errdefer with payload" {
const S = struct {
fn foo() !i32 {
errdefer |a| {
expectEqual(error.One, a);
}
return error.One;
}
fn doTheTest() void {
expectError(error.One, foo());
}
};
S.doTheTest();
comptime S.doTheTest();
}

View File

@ -159,6 +159,7 @@ test "slice syntax resulting in pointer-to-array" {
testSlice();
testSliceZ();
testSlice0();
testSliceOpt();
testSliceAlign();
}
@ -249,6 +250,13 @@ test "slice syntax resulting in pointer-to-array" {
comptime expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
}
fn testSliceOpt() void {
var array: [2]u8 = [2]u8{ 1, 2 };
var slice: ?[]u8 = &array;
comptime expect(@TypeOf(&array, slice) == ?[]u8);
comptime expect(@TypeOf(slice.?[0..2]) == *[2]u8);
}
fn testSlice0() void {
{
var array = [0]u8{};

View File

@ -1,10 +1,12 @@
// This header is generated by zig from base64.zig
#include "base64.h"
#include <assert.h>
#include <string.h>
#include <stdint.h>
// TODO we would like to #include "base64.h" here but this feature has been disabled in
// the stage1 compiler. Users will have to wait until self-hosted is available for
// the "generate .h file" feature.
size_t decode_base_64(uint8_t *dest_ptr, size_t dest_len, const uint8_t *source_ptr, size_t source_len);
extern int *x_ptr;
int main(int argc, char **argv) {

View File

@ -1,6 +1,12 @@
#include "mathtest.h"
#include <assert.h>
// TODO we would like to #include "mathtest.h" here but this feature has been disabled in
// the stage1 compiler. Users will have to wait until self-hosted is available for
// the "generate .h file" feature.
#include <stdint.h>
int32_t add(int32_t a, int32_t b);
int main(int argc, char **argv) {
assert(add(42, 1337) == 1379);
return 0;

View File

@ -20,6 +20,7 @@ const lib_names = [_][]const u8{
"m",
"pthread",
"rt",
"ld",
};
// fpu/nofpu are hardcoded elsewhere, based on .gnueabi/.gnueabihf with an exception for .arm
@ -154,22 +155,24 @@ pub fn main() !void {
const fn_set = &target_funcs_gop.kv.value.list;
for (lib_names) |lib_name, lib_name_index| {
const basename = try fmt.allocPrint(allocator, "lib{}.abilist", .{lib_name});
const lib_prefix = if (std.mem.eql(u8, lib_name, "ld")) "" else "lib";
const basename = try fmt.allocPrint(allocator, "{}{}.abilist", .{ lib_prefix, lib_name });
const abi_list_filename = blk: {
if (abi_list.targets[0].abi == .gnuabi64 and std.mem.eql(u8, lib_name, "c")) {
const is_c = std.mem.eql(u8, lib_name, "c");
const is_m = std.mem.eql(u8, lib_name, "m");
const is_ld = std.mem.eql(u8, lib_name, "ld");
if (abi_list.targets[0].abi == .gnuabi64 and (is_c or is_ld)) {
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n64", basename });
} else if (abi_list.targets[0].abi == .gnuabin32 and std.mem.eql(u8, lib_name, "c")) {
} else if (abi_list.targets[0].abi == .gnuabin32 and (is_c or is_ld)) {
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "n32", basename });
} else if (abi_list.targets[0].arch != .arm and
abi_list.targets[0].abi == .gnueabihf and
(std.mem.eql(u8, lib_name, "c") or
(std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
(is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
{
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "fpu", basename });
} else if (abi_list.targets[0].arch != .arm and
abi_list.targets[0].abi == .gnueabi and
(std.mem.eql(u8, lib_name, "c") or
(std.mem.eql(u8, lib_name, "m") and abi_list.targets[0].arch == .powerpc)))
(is_c or (is_m and abi_list.targets[0].arch == .powerpc)))
{
break :blk try fs.path.join(allocator, &[_][]const u8{ prefix, abi_list.path, "nofpu", basename });
} else if (abi_list.targets[0].arch == .arm) {
@ -234,8 +237,8 @@ pub fn main() !void {
const vers_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "vers.txt" });
const vers_txt_file = try fs.cwd().createFile(vers_txt_path, .{});
defer vers_txt_file.close();
var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&vers_txt_file.outStream().stream);
const vers_txt = &buffered.stream;
var buffered = std.io.bufferedOutStream(vers_txt_file.outStream());
const vers_txt = buffered.outStream();
for (global_ver_list) |name, i| {
_ = global_ver_set.put(name, i) catch unreachable;
try vers_txt.print("{}\n", .{name});
@ -246,8 +249,8 @@ pub fn main() !void {
const fns_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "fns.txt" });
const fns_txt_file = try fs.cwd().createFile(fns_txt_path, .{});
defer fns_txt_file.close();
var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&fns_txt_file.outStream().stream);
const fns_txt = &buffered.stream;
var buffered = std.io.bufferedOutStream(fns_txt_file.outStream());
const fns_txt = buffered.outStream();
for (global_fn_list) |name, i| {
const kv = global_fn_set.get(name).?;
kv.value.index = i;
@ -277,8 +280,8 @@ pub fn main() !void {
const abilist_txt_path = try fs.path.join(allocator, &[_][]const u8{ glibc_out_dir, "abi.txt" });
const abilist_txt_file = try fs.cwd().createFile(abilist_txt_path, .{});
defer abilist_txt_file.close();
var buffered = std.io.BufferedOutStream(fs.File.WriteError).init(&abilist_txt_file.outStream().stream);
const abilist_txt = &buffered.stream;
var buffered = std.io.bufferedOutStream(abilist_txt_file.outStream());
const abilist_txt = buffered.outStream();
// first iterate over the abi lists
for (abi_lists) |*abi_list, abi_index| {