Stage2: exported symbol collision detection
This commit is contained in:
@@ -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(
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user