mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
Zcu: don't tell linkers about exports if there are compile errors
In the best case, this is redundant work, because we aren't actually going to emit a working binary this update. In the worst case, it causes bugs because the linker may not have *seen* the thing being exported due to the compile errors. Resolves: #24417
This commit is contained in:
parent
ce2c9399dd
commit
8adabaa4ed
3 changed files with 28 additions and 12 deletions
|
|
@ -4254,14 +4254,10 @@ fn appendCompileLogLines(log_text: *std.ArrayListUnmanaged(u8), zcu: *Zcu, loggi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn anyErrors(comp: *Compilation) bool {
|
pub fn anyErrors(comp: *Compilation) bool {
|
||||||
return (totalErrorCount(comp) catch return true) != 0;
|
var errors = comp.getAllErrorsAlloc() catch return true;
|
||||||
}
|
|
||||||
|
|
||||||
fn totalErrorCount(comp: *Compilation) !u32 {
|
|
||||||
var errors = try comp.getAllErrorsAlloc();
|
|
||||||
defer errors.deinit(comp.gpa);
|
defer errors.deinit(comp.gpa);
|
||||||
return errors.errorMessageCount();
|
return errors.errorMessageCount() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ErrorNoteHashContext = struct {
|
pub const ErrorNoteHashContext = struct {
|
||||||
|
|
|
||||||
|
|
@ -3149,18 +3149,23 @@ pub fn processExports(pt: Zcu.PerThread) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are compile errors, we won't call `updateExports`. Not only would it be redundant
|
||||||
|
// work, but the linker may not have seen an exported `Nav` due to a compile error, so linker
|
||||||
|
// implementations would have to handle that case. This early return avoids that.
|
||||||
|
const skip_linker_work = zcu.comp.anyErrors();
|
||||||
|
|
||||||
// Map symbol names to `Export` for name collision detection.
|
// Map symbol names to `Export` for name collision detection.
|
||||||
var symbol_exports: SymbolExports = .{};
|
var symbol_exports: SymbolExports = .{};
|
||||||
defer symbol_exports.deinit(gpa);
|
defer symbol_exports.deinit(gpa);
|
||||||
|
|
||||||
for (nav_exports.keys(), nav_exports.values()) |exported_nav, exports_list| {
|
for (nav_exports.keys(), nav_exports.values()) |exported_nav, exports_list| {
|
||||||
const exported: Zcu.Exported = .{ .nav = exported_nav };
|
const exported: Zcu.Exported = .{ .nav = exported_nav };
|
||||||
try pt.processExportsInner(&symbol_exports, exported, exports_list.items);
|
try pt.processExportsInner(&symbol_exports, exported, exports_list.items, skip_linker_work);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uav_exports.keys(), uav_exports.values()) |exported_uav, exports_list| {
|
for (uav_exports.keys(), uav_exports.values()) |exported_uav, exports_list| {
|
||||||
const exported: Zcu.Exported = .{ .uav = exported_uav };
|
const exported: Zcu.Exported = .{ .uav = exported_uav };
|
||||||
try pt.processExportsInner(&symbol_exports, exported, exports_list.items);
|
try pt.processExportsInner(&symbol_exports, exported, exports_list.items, skip_linker_work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3171,6 +3176,7 @@ fn processExportsInner(
|
||||||
symbol_exports: *SymbolExports,
|
symbol_exports: *SymbolExports,
|
||||||
exported: Zcu.Exported,
|
exported: Zcu.Exported,
|
||||||
export_indices: []const Zcu.Export.Index,
|
export_indices: []const Zcu.Export.Index,
|
||||||
|
skip_linker_work: bool,
|
||||||
) error{OutOfMemory}!void {
|
) error{OutOfMemory}!void {
|
||||||
const zcu = pt.zcu;
|
const zcu = pt.zcu;
|
||||||
const gpa = zcu.gpa;
|
const gpa = zcu.gpa;
|
||||||
|
|
@ -3216,13 +3222,14 @@ fn processExportsInner(
|
||||||
}
|
}
|
||||||
break :failed false;
|
break :failed false;
|
||||||
}) {
|
}) {
|
||||||
// This `Decl` is failed, so was never sent to codegen.
|
// This `Nav` is failed, so was never sent to codegen. There should be a compile error.
|
||||||
// TODO: we should probably tell the backend to delete any old exports of this `Decl`?
|
assert(skip_linker_work);
|
||||||
return;
|
|
||||||
},
|
},
|
||||||
.uav => {},
|
.uav => {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (skip_linker_work) return;
|
||||||
|
|
||||||
if (zcu.llvm_object) |llvm_object| {
|
if (zcu.llvm_object) |llvm_object| {
|
||||||
try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
|
try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
|
||||||
} else if (zcu.comp.bin_file) |lf| {
|
} else if (zcu.comp.bin_file) |lf| {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
export fn foo() void {
|
||||||
|
const S = struct { x: u32 = "bad default" };
|
||||||
|
const s: S = undefined;
|
||||||
|
_ = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test case explicitly runs on the LLVM backend as well as self-hosted, as
|
||||||
|
// the original bug leading to this test occurred only with the LLVM backend.
|
||||||
|
|
||||||
|
// error
|
||||||
|
// backend=stage2,llvm
|
||||||
|
//
|
||||||
|
// :2:33: error: expected type 'u32', found '*const [11:0]u8'
|
||||||
Loading…
Add table
Reference in a new issue