Stage2: exported symbol collision detection

This commit is contained in:
Noam Preil
2020-06-26 03:17:13 -04:00
parent e5a3cb8d71
commit 4a17e008da
2 changed files with 65 additions and 17 deletions

View File

@@ -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(

View File

@@ -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 {}