diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index e056b02b2e..e3233c6403 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -949,10 +949,8 @@ pub fn update(self: *Module) !void { try self.deleteDecl(decl); } - if (self.totalErrorCount() == 0) { - // This is needed before reading the error flags. - try self.bin_file.flush(); - } + // This is needed before reading the error flags. + try self.bin_file.flush(); self.link_error_flags = self.bin_file.errorFlags(); @@ -2537,7 +2535,7 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst } } - return self.fail(scope, inst.src, "TODO implement type coercion from {} to {}", .{ inst.ty, dest_type }); + return self.fail(scope, inst.src, "expected {}, found {}", .{ dest_type, inst.ty }); } pub fn storePtr(self: *Module, scope: *Scope, src: usize, ptr: *Inst, uncasted_value: *Inst) !*Inst { diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 6fd9329188..8bfd3bdb48 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -1172,7 +1172,10 @@ pub const File = struct { self.debug_aranges_section_dirty = false; } - if (self.debug_line_header_dirty) { + if (self.debug_line_header_dirty) debug_line: { + if (self.dbg_line_fn_first == null) { + break :debug_line; // Error in module; leave debug_line_header_dirty=true. + } const dbg_line_prg_off = self.getDebugLineProgramOff(); const dbg_line_prg_end = self.getDebugLineProgramEnd(); assert(dbg_line_prg_end != 0); @@ -1403,18 +1406,21 @@ pub const File = struct { self.shdr_table_dirty = false; } if (self.entry_addr == null and self.base.options.output_mode == .Exe) { - log.debug(.link, "no_entry_point_found = true\n", .{}); + log.debug(.link, "flushing. no_entry_point_found = true\n", .{}); self.error_flags.no_entry_point_found = true; } else { + log.debug(.link, "flushing. no_entry_point_found = false\n", .{}); self.error_flags.no_entry_point_found = false; try self.writeElfHeader(); } - // The point of flush() is to commit changes, so nothing should be dirty after this. + // The point of flush() is to commit changes, so in theory, nothing should + // be dirty after this. However, it is possible for some things to remain + // dirty because they fail to be written in the event of compile errors, + // such as debug_line_header_dirty. assert(!self.debug_info_section_dirty); assert(!self.debug_abbrev_section_dirty); assert(!self.debug_aranges_section_dirty); - assert(!self.debug_line_header_dirty); assert(!self.phdr_table_dirty); assert(!self.shdr_table_dirty); assert(!self.shstrtab_dirty); diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 5e2120f41a..2795da0017 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -64,6 +64,9 @@ var general_purpose_allocator = std.heap.GeneralPurposeAllocator(.{}){}; pub fn main() !void { const gpa = if (std.builtin.link_libc) std.heap.c_allocator else &general_purpose_allocator.allocator; + defer if (!std.builtin.link_libc) { + _ = general_purpose_allocator.deinit(); + }; var arena_instance = std.heap.ArenaAllocator.init(gpa); defer arena_instance.deinit(); const arena = &arena_instance.allocator; diff --git a/test/stage2/compare_output.zig b/test/stage2/compare_output.zig index 1e4db06572..bb3e542f13 100644 --- a/test/stage2/compare_output.zig +++ b/test/stage2/compare_output.zig @@ -23,6 +23,9 @@ pub fn addCases(ctx: *TestContext) !void { { var case = ctx.exe("hello world with updates", linux_x64); + + case.addError("", &[_][]const u8{":1:1: error: no entry point found"}); + // Regular old hello world case.addCompareOutput( \\export fn _start() noreturn { @@ -123,7 +126,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ ); } - + { var case = ctx.exe("hello world", linux_riscv64); // Regular old hello world