Commit 4a17e008da
Changed files (2)
src-self-hosted
test
stage2
src-self-hosted/Module.zig
@@ -2120,6 +2120,20 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
else => return self.fail(scope, src, "unable to export type '{}'", .{typed_value.ty}),
}
+ var already_exported = false;
+ {
+ var it = self.decl_exports.iterator();
+ while (it.next()) |kv| {
+ const export_list = kv.value;
+ for (export_list) |e| {
+ if (std.mem.eql(u8, e.options.name, symbol_name)) {
+ already_exported = true;
+ break;
+ }
+ }
+ }
+ }
+
try self.decl_exports.ensureCapacity(self.decl_exports.size + 1);
try self.export_owners.ensureCapacity(self.export_owners.size + 1);
@@ -2155,19 +2169,29 @@ fn analyzeExport(self: *Module, scope: *Scope, src: usize, symbol_name: []const
de_gop.kv.value[de_gop.kv.value.len - 1] = new_export;
errdefer de_gop.kv.value = self.allocator.shrink(de_gop.kv.value, de_gop.kv.value.len - 1);
- self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- else => {
- try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
- self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
- self.allocator,
- src,
- "unable to export: {}",
- .{@errorName(err)},
- ));
- new_export.status = .failed_retryable;
- },
- };
+ if (already_exported) {
+ try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
+ self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
+ self.allocator,
+ src,
+ "exported symbol collision: {}",
+ .{symbol_name},
+ ));
+ } else {
+ self.bin_file.updateDeclExports(self, exported_decl, de_gop.kv.value) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ else => {
+ try self.failed_exports.ensureCapacity(self.failed_exports.size + 1);
+ self.failed_exports.putAssumeCapacityNoClobber(new_export, try ErrorMsg.create(
+ self.allocator,
+ src,
+ "unable to export: {}",
+ .{@errorName(err)},
+ ));
+ new_export.status = .failed_retryable;
+ },
+ };
+ }
}
fn addNewInstArgs(
test/stage2/compile_errors.zig
@@ -43,13 +43,37 @@ pub fn addCases(ctx: *TestContext) !void {
\\@1 = export(@0, "start")
, &[_][]const u8{":4:9: error: unable to call function with naked calling convention"});
+ {
+ var case = ctx.objZIR("exported symbol collision", linux_x64);
+ // First, ensure we receive the error correctly
+ case.addError(
+ \\@noreturn = primitive(noreturn)
+ \\
+ \\@start_fnty = fntype([], @noreturn)
+ \\@start = fn(@start_fnty, {})
+ \\
+ \\@0 = str("_start")
+ \\@1 = export(@0, "start")
+ \\@2 = export(@0, "start")
+ , &[_][]const u8{":8:13: error: exported symbol collision: _start"});
+ // Next, ensure everything works properly on the next compilation with the problem fixed
+ case.compiles(
+ \\@noreturn = primitive(noreturn)
+ \\
+ \\@start_fnty = fntype([], @noreturn)
+ \\@start = fn(@start_fnty, {})
+ \\
+ \\@0 = str("_start")
+ \\@1 = export(@0, "start")
+ );
+ }
// TODO: re-enable these tests.
// https://github.com/ziglang/zig/issues/1364
- // ctx.addError("Export same symbol twice", linux_x64, .Zig,
- // \\export fn entry() void {}
- // \\export fn entry() void {}
- // , &[_][]const u8{":2:1: error: exported symbol collision"});
+ // ctx.compileError("Export same symbol twice", linux_x64,
+ // \\export fn entry() void {}
+ // \\export fn entry() void {}
+ // , &[_][]const u8{":2:1: error: exported symbol collision"});
// ctx.addError("Missing function name", linux_x64, .Zig,
// \\fn() void {}