authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-09 18:55:58+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-09-15 00:50:18+03:00
log31daea74d23be813737892a166cc16ade1272a1a
treeb25f5d80c2a9c63fe6d0099af5f89d38ed492112
parent5e4483fff8077ec8d87ba9125f946955a34b6fc0

stage2: implement referenced by trace for error messages

Closes #7668 Closes #12141

8 files changed, 197 insertions(+), 40 deletions(-)

lib/build_runner.zig+12
......@@ -185,6 +185,16 @@ pub fn main() !void {
185185 builder.use_stage1 = true;
186186 } else if (mem.eql(u8, arg, "-fno-stage1")) {
187187 builder.use_stage1 = false;
188 } else if (mem.eql(u8, arg, "-freference-trace")) {
189 builder.reference_trace = 256;
190 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
191 const num = arg["-freference-trace=".len..];
192 builder.reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
193 std.debug.print("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });
194 process.exit(1);
195 };
196 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
197 builder.reference_trace = null;
188198 } else if (mem.eql(u8, arg, "--")) {
189199 builder.args = argsRest(args, arg_idx);
190200 break;
......@@ -308,6 +318,8 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
308318 \\Advanced Options:
309319 \\ -fstage1 Force using bootstrap compiler as the codegen backend
310320 \\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
321 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
322 \\ -fno-reference-trace Disable reference trace
311323 \\ --build-file [file] Override path to build.zig
312324 \\ --cache-dir [path] Override path to local Zig cache directory
313325 \\ --global-cache-dir [path] Override path to global Zig cache directory
lib/std/build.zig+5
......@@ -45,6 +45,7 @@ pub const Builder = struct {
4545 /// The purpose of executing the command is for a human to read compile errors from the terminal
4646 prominent_compile_errors: bool,
4747 color: enum { auto, on, off } = .auto,
48 reference_trace: ?u32 = null,
4849 use_stage1: ?bool = null,
4950 invalid_user_input: bool,
5051 zig_exe: []const u8,
......@@ -2475,6 +2476,10 @@ pub const LibExeObjStep = struct {
24752476 try zig_args.append(@tagName(builder.color));
24762477 }
24772478
2479 if (builder.reference_trace) |some| {
2480 try zig_args.append(try std.fmt.allocPrint(builder.allocator, "-freference-trace={d}", .{some}));
2481 }
2482
24782483 if (self.use_stage1) |stage1| {
24792484 if (stage1) {
24802485 try zig_args.append("-fstage1");
src/Compilation.zig+62
......@@ -154,6 +154,10 @@ owned_link_dir: ?std.fs.Dir,
154154/// Don't use this for anything other than stage1 compatibility.
155155color: Color = .auto,
156156
157/// How many lines of reference trace should be included per compile error.
158/// Null means only show snippet on first error.
159reference_trace: ?u32 = null,
160
157161libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default,
158162
159163/// This mutex guards all `Compilation` mutable state.
......@@ -348,6 +352,7 @@ pub const AllErrors = struct {
348352 /// Does not include the trailing newline.
349353 source_line: ?[]const u8,
350354 notes: []Message = &.{},
355 reference_trace: []Message = &.{},
351356
352357 /// Splits the error message up into lines to properly indent them
353358 /// to allow for long, good-looking error messages.
......@@ -447,6 +452,34 @@ pub const AllErrors = struct {
447452 for (src.notes) |note| {
448453 try note.renderToWriter(ttyconf, stderr, "note", .Cyan, indent);
449454 }
455 if (src.reference_trace.len != 0) {
456 ttyconf.setColor(stderr, .Reset);
457 ttyconf.setColor(stderr, .Dim);
458 try stderr.print("referenced by:\n", .{});
459 for (src.reference_trace) |reference| {
460 switch (reference) {
461 .src => |ref_src| try stderr.print(" {s}: {s}:{d}:{d}\n", .{
462 ref_src.msg,
463 ref_src.src_path,
464 ref_src.line + 1,
465 ref_src.column + 1,
466 }),
467 .plain => |plain| if (plain.count != 0) {
468 try stderr.print(
469 " {d} reference(s) hidden; use '-freference-trace={d}' to see all references\n",
470 .{ plain.count, plain.count + src.reference_trace.len - 1 },
471 );
472 } else {
473 try stderr.print(
474 " remaining reference traces hidden; use '-freference-trace' to see all reference traces\n",
475 .{},
476 );
477 },
478 }
479 }
480 try stderr.writeByte('\n');
481 ttyconf.setColor(stderr, .Reset);
482 }
450483 },
451484 .plain => |plain| {
452485 ttyconf.setColor(stderr, color);
......@@ -572,6 +605,32 @@ pub const AllErrors = struct {
572605 });
573606 return;
574607 }
608
609 const reference_trace = try allocator.alloc(Message, module_err_msg.reference_trace.len);
610 for (reference_trace) |*reference, i| {
611 const module_reference = module_err_msg.reference_trace[i];
612 if (module_reference.hidden != 0) {
613 reference.* = .{ .plain = .{ .msg = undefined, .count = module_reference.hidden } };
614 break;
615 } else if (module_reference.decl == null) {
616 reference.* = .{ .plain = .{ .msg = undefined, .count = 0 } };
617 break;
618 }
619 const source = try module_reference.src_loc.file_scope.getSource(module.gpa);
620 const span = try module_reference.src_loc.span(module.gpa);
621 const loc = std.zig.findLineColumn(source.bytes, span.main);
622 const file_path = try module_reference.src_loc.file_scope.fullPath(allocator);
623 reference.* = .{
624 .src = .{
625 .src_path = file_path,
626 .msg = try allocator.dupe(u8, std.mem.sliceTo(module_reference.decl.?, 0)),
627 .span = span,
628 .line = @intCast(u32, loc.line),
629 .column = @intCast(u32, loc.column),
630 .source_line = null,
631 },
632 };
633 }
575634 const file_path = try module_err_msg.src_loc.file_scope.fullPath(allocator);
576635 try errors.append(.{
577636 .src = .{
......@@ -581,6 +640,7 @@ pub const AllErrors = struct {
581640 .line = @intCast(u32, err_loc.line),
582641 .column = @intCast(u32, err_loc.column),
583642 .notes = notes_buf[0..note_i],
643 .reference_trace = reference_trace,
584644 .source_line = try allocator.dupe(u8, err_loc.source_line),
585645 },
586646 });
......@@ -929,6 +989,7 @@ pub const InitOptions = struct {
929989 clang_preprocessor_mode: ClangPreprocessorMode = .no,
930990 /// This is for stage1 and should be deleted upon completion of self-hosting.
931991 color: Color = .auto,
992 reference_trace: ?u32 = null,
932993 test_filter: ?[]const u8 = null,
933994 test_name_prefix: ?[]const u8 = null,
934995 subsystem: ?std.Target.SubSystem = null,
......@@ -1838,6 +1899,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation {
18381899 .disable_c_depfile = options.disable_c_depfile,
18391900 .owned_link_dir = owned_link_dir,
18401901 .color = options.color,
1902 .reference_trace = options.reference_trace,
18411903 .time_report = options.time_report,
18421904 .stack_report = options.stack_report,
18431905 .unwind_tables = unwind_tables,
src/Module.zig+20
......@@ -166,6 +166,11 @@ decls_free_list: std.ArrayListUnmanaged(Decl.Index) = .{},
166166
167167global_assembly: std.AutoHashMapUnmanaged(Decl.Index, []u8) = .{},
168168
169reference_table: std.AutoHashMapUnmanaged(Decl.Index, struct {
170 referencer: Decl.Index,
171 src: LazySrcLoc,
172}) = .{},
173
169174pub const StringLiteralContext = struct {
170175 bytes: *std.ArrayListUnmanaged(u8),
171176
......@@ -2084,6 +2089,13 @@ pub const ErrorMsg = struct {
20842089 src_loc: SrcLoc,
20852090 msg: []const u8,
20862091 notes: []ErrorMsg = &.{},
2092 reference_trace: []Trace = &.{},
2093
2094 pub const Trace = struct {
2095 decl: ?[*:0]const u8,
2096 src_loc: SrcLoc,
2097 hidden: u32 = 0,
2098 };
20872099
20882100 pub fn create(
20892101 gpa: Allocator,
......@@ -2122,8 +2134,15 @@ pub const ErrorMsg = struct {
21222134 }
21232135 gpa.free(err_msg.notes);
21242136 gpa.free(err_msg.msg);
2137 gpa.free(err_msg.reference_trace);
21252138 err_msg.* = undefined;
21262139 }
2140
2141 pub fn clearTrace(err_msg: *ErrorMsg, gpa: Allocator) void {
2142 if (err_msg.reference_trace.len == 0) return;
2143 gpa.free(err_msg.reference_trace);
2144 err_msg.reference_trace = &.{};
2145 }
21272146};
21282147
21292148/// Canonical reference to a position within a source file.
......@@ -3411,6 +3430,7 @@ pub fn deinit(mod: *Module) void {
34113430 mod.decls_free_list.deinit(gpa);
34123431 mod.allocated_decls.deinit(gpa);
34133432 mod.global_assembly.deinit(gpa);
3433 mod.reference_table.deinit(gpa);
34143434
34153435 mod.string_literal_table.deinit(gpa);
34163436 mod.string_literal_bytes.deinit(gpa);
src/Sema.zig+62-25
......@@ -111,6 +111,7 @@ const crash_report = @import("crash_report.zig");
111111const build_options = @import("build_options");
112112
113113pub const default_branch_quota = 1000;
114pub const default_reference_trace_len = 2;
114115
115116pub const InstMap = std.AutoHashMapUnmanaged(Zir.Inst.Index, Air.Inst.Ref);
116117
......@@ -1958,13 +1959,53 @@ fn failWithOwnedErrorMsg(sema: *Sema, err_msg: *Module.ErrorMsg) CompileError {
19581959 }
19591960
19601961 const mod = sema.mod;
1961 {
1962 ref: {
19621963 errdefer err_msg.destroy(mod.gpa);
19631964 if (err_msg.src_loc.lazy == .unneeded) {
19641965 return error.NeededSourceLocation;
19651966 }
19661967 try mod.failed_decls.ensureUnusedCapacity(mod.gpa, 1);
19671968 try mod.failed_files.ensureUnusedCapacity(mod.gpa, 1);
1969
1970 const max_references = blk: {
1971 if (sema.mod.comp.reference_trace) |num| break :blk num;
1972 // Do not add multiple traces without explicit request.
1973 if (sema.mod.failed_decls.count() != 0) break :ref;
1974 break :blk default_reference_trace_len;
1975 };
1976
1977 var referenced_by = if (sema.func) |some| some.owner_decl else sema.owner_decl_index;
1978 var reference_stack = std.ArrayList(Module.ErrorMsg.Trace).init(sema.gpa);
1979 defer reference_stack.deinit();
1980
1981 // Avoid infinite loops.
1982 var seen = std.AutoHashMap(Module.Decl.Index, void).init(sema.gpa);
1983 defer seen.deinit();
1984
1985 var cur_reference_trace: u32 = 0;
1986 while (sema.mod.reference_table.get(referenced_by)) |ref| : (cur_reference_trace += 1) {
1987 const gop = try seen.getOrPut(ref.referencer);
1988 if (gop.found_existing) break;
1989 if (cur_reference_trace < max_references) {
1990 const decl = sema.mod.declPtr(ref.referencer);
1991 try reference_stack.append(.{ .decl = decl.name, .src_loc = ref.src.toSrcLoc(decl) });
1992 }
1993 referenced_by = ref.referencer;
1994 }
1995 if (sema.mod.comp.reference_trace == null and cur_reference_trace > 0) {
1996 try reference_stack.append(.{
1997 .decl = null,
1998 .src_loc = undefined,
1999 .hidden = 0,
2000 });
2001 } else if (cur_reference_trace > max_references) {
2002 try reference_stack.append(.{
2003 .decl = undefined,
2004 .src_loc = undefined,
2005 .hidden = cur_reference_trace - max_references,
2006 });
2007 }
2008 err_msg.reference_trace = reference_stack.toOwnedSlice();
19682009 }
19692010 if (sema.owner_func) |func| {
19702011 func.state = .sema_failure;
......@@ -5366,14 +5407,8 @@ fn zirDeclRef(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
53665407 const src = inst_data.src();
53675408 const decl_name = inst_data.get(sema.code);
53685409 const decl_index = try sema.lookupIdentifier(block, src, decl_name);
5369 return sema.analyzeDeclRef(decl_index) catch |err| switch (err) {
5370 error.AnalysisFail => {
5371 const msg = sema.err orelse return err;
5372 try sema.errNote(block, src, msg, "referenced here", .{});
5373 return err;
5374 },
5375 else => return err,
5376 };
5410 try sema.addReferencedBy(block, src, decl_index);
5411 return sema.analyzeDeclRef(decl_index);
53775412}
53785413
53795414fn zirDeclVal(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
......@@ -6107,6 +6142,7 @@ fn analyzeCall(
61076142 error.AnalysisFail => {
61086143 const err_msg = sema.err orelse return err;
61096144 try sema.errNote(block, call_src, err_msg, "called from here", .{});
6145 err_msg.clearTrace(sema.gpa);
61106146 return err;
61116147 },
61126148 else => |e| return e,
......@@ -21741,14 +21777,8 @@ fn namespaceLookupRef(
2174121777 decl_name: []const u8,
2174221778) CompileError!?Air.Inst.Ref {
2174321779 const decl = (try sema.namespaceLookup(block, src, namespace, decl_name)) orelse return null;
21744 return sema.analyzeDeclRef(decl) catch |err| switch (err) {
21745 error.AnalysisFail => {
21746 const msg = sema.err orelse return err;
21747 try sema.errNote(block, src, msg, "referenced here", .{});
21748 return err;
21749 },
21750 else => return err,
21751 };
21780 try sema.addReferencedBy(block, src, decl);
21781 return try sema.analyzeDeclRef(decl);
2175221782}
2175321783
2175421784fn namespaceLookupVal(
......@@ -26001,14 +26031,8 @@ fn analyzeDeclVal(
2600126031 if (sema.decl_val_table.get(decl_index)) |result| {
2600226032 return result;
2600326033 }
26004 const decl_ref = sema.analyzeDeclRef(decl_index) catch |err| switch (err) {
26005 error.AnalysisFail => {
26006 const msg = sema.err orelse return err;
26007 try sema.errNote(block, src, msg, "referenced here", .{});
26008 return err;
26009 },
26010 else => return err,
26011 };
26034 try sema.addReferencedBy(block, src, decl_index);
26035 const decl_ref = try sema.analyzeDeclRef(decl_index);
2601226036 const result = try sema.analyzeLoad(block, src, decl_ref, src);
2601326037 if (Air.refToIndex(result)) |index| {
2601426038 if (sema.air_instructions.items(.tag)[index] == .constant and !block.is_typeof) {
......@@ -26018,6 +26042,19 @@ fn analyzeDeclVal(
2601826042 return result;
2601926043}
2602026044
26045fn addReferencedBy(
26046 sema: *Sema,
26047 block: *Block,
26048 src: LazySrcLoc,
26049 decl_index: Decl.Index,
26050) !void {
26051 if (sema.mod.comp.reference_trace == @as(u32, 0)) return;
26052 try sema.mod.reference_table.put(sema.gpa, decl_index, .{
26053 .referencer = block.src_decl,
26054 .src = src,
26055 });
26056}
26057
2602126058fn ensureDeclAnalyzed(sema: *Sema, decl_index: Decl.Index) CompileError!void {
2602226059 const decl = sema.mod.declPtr(decl_index);
2602326060 if (decl.analysis == .in_progress) {
src/main.zig+35-14
......@@ -396,6 +396,8 @@ const usage_build_generic =
396396 \\ -fno-Clang Prevent using Clang as the C/C++ compilation backend
397397 \\ -fstage1 Force using bootstrap compiler as the codegen backend
398398 \\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
399 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
400 \\ -fno-reference-trace Disable reference trace
399401 \\ -fsingle-threaded Code assumes there is only one thread
400402 \\ -fno-single-threaded Code may not assume there is only one thread
401403 \\ -fbuiltin Enable implicit builtin knowledge of functions
......@@ -742,6 +744,7 @@ fn buildOutputType(
742744 var headerpad_size: ?u32 = null;
743745 var headerpad_max_install_names: bool = false;
744746 var dead_strip_dylibs: bool = false;
747 var reference_trace: ?u32 = null;
745748
746749 // e.g. -m3dnow or -mno-outline-atomics. They correspond to std.Target llvm cpu feature names.
747750 // This array is populated by zig cc frontend and then has to be converted to zig-style
......@@ -928,14 +931,14 @@ fn buildOutputType(
928931 fatal("expected parameter after {s}", .{arg});
929932 };
930933 stack_size_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
931 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
934 fatal("unable to parse stack size '{s}': {s}", .{ next_arg, @errorName(err) });
932935 };
933936 } else if (mem.eql(u8, arg, "--image-base")) {
934937 const next_arg = args_iter.next() orelse {
935938 fatal("expected parameter after {s}", .{arg});
936939 };
937940 image_base_override = std.fmt.parseUnsigned(u64, next_arg, 0) catch |err| {
938 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
941 fatal("unable to parse image base override '{s}': {s}", .{ next_arg, @errorName(err) });
939942 };
940943 } else if (mem.eql(u8, arg, "--name")) {
941944 provided_name = args_iter.next() orelse {
......@@ -984,7 +987,7 @@ fn buildOutputType(
984987 fatal("expected parameter after {s}", .{arg});
985988 };
986989 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
987 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
990 fatal("unable to parse pagezero size'{s}': {s}", .{ next_arg, @errorName(err) });
988991 };
989992 } else if (mem.eql(u8, arg, "-search_paths_first")) {
990993 search_strategy = .paths_first;
......@@ -995,7 +998,7 @@ fn buildOutputType(
995998 fatal("expected parameter after {s}", .{arg});
996999 };
9971000 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
998 fatal("unable to parser '{s}': {s}", .{ arg, @errorName(err) });
1001 fatal("unable to parse headerpat size '{s}': {s}", .{ next_arg, @errorName(err) });
9991002 };
10001003 } else if (mem.eql(u8, arg, "-headerpad_max_install_names")) {
10011004 headerpad_max_install_names = true;
......@@ -1214,6 +1217,15 @@ fn buildOutputType(
12141217 use_stage1 = true;
12151218 } else if (mem.eql(u8, arg, "-fno-stage1")) {
12161219 use_stage1 = false;
1220 } else if (mem.eql(u8, arg, "-freference-trace")) {
1221 reference_trace = 256;
1222 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
1223 const num = arg["-freference-trace=".len..];
1224 reference_trace = std.fmt.parseUnsigned(u32, num, 10) catch |err| {
1225 fatal("unable to parse reference_trace count '{s}': {s}", .{ num, @errorName(err) });
1226 };
1227 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
1228 reference_trace = null;
12171229 } else if (mem.eql(u8, arg, "-rdynamic")) {
12181230 rdynamic = true;
12191231 } else if (mem.eql(u8, arg, "-fsoname")) {
......@@ -1785,11 +1797,11 @@ fn buildOutputType(
17851797 fatal("expected linker arg after '{s}'", .{arg});
17861798 }
17871799 linker_optimization = std.fmt.parseUnsigned(u8, linker_args.items[i], 10) catch |err| {
1788 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1800 fatal("unable to parse optimization level '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
17891801 };
17901802 } else if (mem.startsWith(u8, arg, "-O")) {
17911803 linker_optimization = std.fmt.parseUnsigned(u8, arg["-O".len..], 10) catch |err| {
1792 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1804 fatal("unable to parse optimization level '{s}': {s}", .{ arg, @errorName(err) });
17931805 };
17941806 } else if (mem.eql(u8, arg, "-pagezero_size")) {
17951807 i += 1;
......@@ -1798,7 +1810,7 @@ fn buildOutputType(
17981810 }
17991811 const next_arg = linker_args.items[i];
18001812 pagezero_size = std.fmt.parseUnsigned(u64, eatIntPrefix(next_arg, 16), 16) catch |err| {
1801 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1813 fatal("unable to parse pagezero size '{s}': {s}", .{ next_arg, @errorName(err) });
18021814 };
18031815 } else if (mem.eql(u8, arg, "-headerpad")) {
18041816 i += 1;
......@@ -1807,7 +1819,7 @@ fn buildOutputType(
18071819 }
18081820 const next_arg = linker_args.items[i];
18091821 headerpad_size = std.fmt.parseUnsigned(u32, eatIntPrefix(next_arg, 16), 16) catch |err| {
1810 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1822 fatal("unable to parse headerpad size '{s}': {s}", .{ next_arg, @errorName(err) });
18111823 };
18121824 } else if (mem.eql(u8, arg, "-headerpad_max_install_names")) {
18131825 headerpad_max_install_names = true;
......@@ -1899,7 +1911,7 @@ fn buildOutputType(
18991911 fatal("expected linker arg after '{s}'", .{arg});
19001912 }
19011913 version.major = std.fmt.parseUnsigned(u32, linker_args.items[i], 10) catch |err| {
1902 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1914 fatal("unable to parse major image version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
19031915 };
19041916 have_version = true;
19051917 } else if (mem.eql(u8, arg, "--minor-image-version")) {
......@@ -1908,7 +1920,7 @@ fn buildOutputType(
19081920 fatal("expected linker arg after '{s}'", .{arg});
19091921 }
19101922 version.minor = std.fmt.parseUnsigned(u32, linker_args.items[i], 10) catch |err| {
1911 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1923 fatal("unable to parse minor image version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
19121924 };
19131925 have_version = true;
19141926 } else if (mem.eql(u8, arg, "-e") or mem.eql(u8, arg, "--entry")) {
......@@ -1923,7 +1935,7 @@ fn buildOutputType(
19231935 fatal("expected linker arg after '{s}'", .{arg});
19241936 }
19251937 stack_size_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| {
1926 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1938 fatal("unable to parse stack size override '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
19271939 };
19281940 } else if (mem.eql(u8, arg, "--image-base")) {
19291941 i += 1;
......@@ -1931,7 +1943,7 @@ fn buildOutputType(
19311943 fatal("expected linker arg after '{s}'", .{arg});
19321944 }
19331945 image_base_override = std.fmt.parseUnsigned(u64, linker_args.items[i], 0) catch |err| {
1934 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1946 fatal("unable to parse image base override '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
19351947 };
19361948 } else if (mem.eql(u8, arg, "-T") or mem.eql(u8, arg, "--script")) {
19371949 i += 1;
......@@ -1984,7 +1996,7 @@ fn buildOutputType(
19841996 linker_args.items[i],
19851997 10,
19861998 ) catch |err| {
1987 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
1999 fatal("unable to parse major subsystem version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
19882000 };
19892001 } else if (mem.eql(u8, arg, "--minor-subsystem-version")) {
19902002 i += 1;
......@@ -1997,7 +2009,7 @@ fn buildOutputType(
19972009 linker_args.items[i],
19982010 10,
19992011 ) catch |err| {
2000 fatal("unable to parse '{s}': {s}", .{ arg, @errorName(err) });
2012 fatal("unable to parse minor subsystem version '{s}': {s}", .{ linker_args.items[i], @errorName(err) });
20012013 };
20022014 } else if (mem.eql(u8, arg, "-framework")) {
20032015 i += 1;
......@@ -2981,6 +2993,7 @@ fn buildOutputType(
29812993 .headerpad_size = headerpad_size,
29822994 .headerpad_max_install_names = headerpad_max_install_names,
29832995 .dead_strip_dylibs = dead_strip_dylibs,
2996 .reference_trace = reference_trace,
29842997 }) catch |err| switch (err) {
29852998 error.LibCUnavailable => {
29862999 const target = target_info.target;
......@@ -3740,6 +3753,8 @@ pub const usage_build =
37403753 \\Options:
37413754 \\ -fstage1 Force using bootstrap compiler as the codegen backend
37423755 \\ -fno-stage1 Prevent using bootstrap compiler as the codegen backend
3756 \\ -freference-trace[=num] How many lines of reference trace should be shown per compile error
3757 \\ -fno-reference-trace Disable reference trace
37433758 \\ --build-file [file] Override path to build.zig
37443759 \\ --cache-dir [path] Override path to local Zig cache directory
37453760 \\ --global-cache-dir [path] Override path to global Zig cache directory
......@@ -3812,6 +3827,12 @@ pub fn cmdBuild(gpa: Allocator, arena: Allocator, args: []const []const u8) !voi
38123827 } else if (mem.eql(u8, arg, "-fno-stage1")) {
38133828 use_stage1 = false;
38143829 try child_argv.append(arg);
3830 } else if (mem.eql(u8, arg, "-freference-trace")) {
3831 try child_argv.append(arg);
3832 } else if (mem.startsWith(u8, arg, "-freference-trace=")) {
3833 try child_argv.append(arg);
3834 } else if (mem.eql(u8, arg, "-fno-reference-trace")) {
3835 try child_argv.append(arg);
38153836 }
38163837 }
38173838 try child_argv.append(arg);
src/test.zig+1
......@@ -1548,6 +1548,7 @@ pub const TestContext = struct {
15481548 .self_exe_path = std.testing.zig_exe_path,
15491549 // TODO instead of turning off color, pass in a std.Progress.Node
15501550 .color = .off,
1551 .reference_trace = 0,
15511552 // TODO: force self-hosted linkers with stage2 backend to avoid LLD creeping in
15521553 // until the auto-select mechanism deems them worthy
15531554 .use_lld = switch (case.backend) {
test/cases/compile_errors/top_level_decl_dependency_loop.zig-1
......@@ -10,4 +10,3 @@ export fn entry() void {
1010// target=native
1111//
1212// :1:1: error: dependency loop detected
13// :2:19: note: referenced here