aboutsummaryrefslogtreecommitdiff
path: root/src/Zcu/PerThread.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2025-08-15 11:18:45 +0100
committerMatthew Lugg <mlugg@mlugg.co.uk>2025-08-15 20:00:30 +0100
commit8adabaa4ed2321882e2ef04ebb2d9b621805aac2 (patch)
treea1ff7a83fbfcd976d17b1f19cd1e848c08da0793 /src/Zcu/PerThread.zig
parentce2c9399dd44943079dde5c00af4fead01d3d9ef (diff)
downloadzig-8adabaa4ed2321882e2ef04ebb2d9b621805aac2.tar.gz
zig-8adabaa4ed2321882e2ef04ebb2d9b621805aac2.zip
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
Diffstat (limited to 'src/Zcu/PerThread.zig')
-rw-r--r--src/Zcu/PerThread.zig17
1 files changed, 12 insertions, 5 deletions
diff --git a/src/Zcu/PerThread.zig b/src/Zcu/PerThread.zig
index 5a76760540..6d2da7afa4 100644
--- a/src/Zcu/PerThread.zig
+++ b/src/Zcu/PerThread.zig
@@ -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.
var symbol_exports: SymbolExports = .{};
defer symbol_exports.deinit(gpa);
for (nav_exports.keys(), nav_exports.values()) |exported_nav, exports_list| {
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| {
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,
exported: Zcu.Exported,
export_indices: []const Zcu.Export.Index,
+ skip_linker_work: bool,
) error{OutOfMemory}!void {
const zcu = pt.zcu;
const gpa = zcu.gpa;
@@ -3216,13 +3222,14 @@ fn processExportsInner(
}
break :failed false;
}) {
- // This `Decl` is failed, so was never sent to codegen.
- // TODO: we should probably tell the backend to delete any old exports of this `Decl`?
- return;
+ // This `Nav` is failed, so was never sent to codegen. There should be a compile error.
+ assert(skip_linker_work);
},
.uav => {},
}
+ if (skip_linker_work) return;
+
if (zcu.llvm_object) |llvm_object| {
try zcu.handleUpdateExports(export_indices, llvm_object.updateExports(pt, exported, export_indices));
} else if (zcu.comp.bin_file) |lf| {