| author | |
| committer | |
| log | fd634f3db35791ea904e82a525e4f49f4c5b67a8 |
| tree | b6e44cde3540f2ecf26724e830a8110020546d25 |
| parent | d6856859d3082d9b66aac7c25ceb2abcd13e2f7c |
closes #2754 files changed, 46 insertions(+), 8 deletions(-)
src/all_types.hpp+1| ... | ... | @@ -1293,6 +1293,7 @@ struct CodeGen { |
| 1293 | 1293 | HashMap<Scope *, IrInstruction *, fn_eval_hash, fn_eval_eql> memoized_fn_eval_table; |
| 1294 | 1294 | HashMap<ZigLLVMFnKey, LLVMValueRef, zig_llvm_fn_key_hash, zig_llvm_fn_key_eql> llvm_fn_table; |
| 1295 | 1295 | HashMap<Buf *, ConstExprValue *, buf_hash, buf_eql_buf> compile_vars; |
| 1296 | HashMap<Buf *, Tld *, buf_hash, buf_eql_buf> external_symbol_names; | |
| 1296 | 1297 | |
| 1297 | 1298 | ZigList<ImportTableEntry *> import_queue; |
| 1298 | 1299 | size_t import_queue_index; |
src/analyze.cpp+10| ... | ... | @@ -1904,6 +1904,16 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) { |
| 1904 | 1904 | g->resolve_queue.append(tld); |
| 1905 | 1905 | } |
| 1906 | 1906 | |
| 1907 | if (tld->visib_mod == VisibModExport) { | |
| 1908 | auto entry = g->external_symbol_names.put_unique(tld->name, tld); | |
| 1909 | if (entry) { | |
| 1910 | Tld *other_tld = entry->value; | |
| 1911 | ErrorMsg *msg = add_node_error(g, tld->source_node, | |
| 1912 | buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name))); | |
| 1913 | add_error_note(g, msg, other_tld->source_node, buf_sprintf("other symbol is here")); | |
| 1914 | } | |
| 1915 | } | |
| 1916 | ||
| 1907 | 1917 | auto entry = decls_scope->decl_table.put_unique(tld->name, tld); |
| 1908 | 1918 | if (entry) { |
| 1909 | 1919 | Tld *other_tld = entry->value; |
src/codegen.cpp+17-7| ... | ... | @@ -67,6 +67,7 @@ CodeGen *codegen_create(Buf *root_source_dir, const ZigTarget *target) { |
| 67 | 67 | g->llvm_fn_table.init(16); |
| 68 | 68 | g->memoized_fn_eval_table.init(16); |
| 69 | 69 | g->compile_vars.init(16); |
| 70 | g->external_symbol_names.init(8); | |
| 70 | 71 | g->is_release_build = false; |
| 71 | 72 | g->is_test_build = false; |
| 72 | 73 | g->want_h_file = true; |
| ... | ... | @@ -260,16 +261,25 @@ static void addLLVMArgAttr(LLVMValueRef arg_val, unsigned param_index, const cha |
| 260 | 261 | return addLLVMAttr(arg_val, param_index + 1, attr_name); |
| 261 | 262 | } |
| 262 | 263 | |
| 264 | static Buf *get_mangled_name(CodeGen *g, Buf *original_name, bool external_linkage) { | |
| 265 | if (external_linkage || g->external_symbol_names.maybe_get(original_name) == nullptr) { | |
| 266 | return original_name; | |
| 267 | } | |
| 268 | ||
| 269 | int n = 0; | |
| 270 | for (;; n += 1) { | |
| 271 | Buf *new_name = buf_sprintf("%s.%d", buf_ptr(original_name), n); | |
| 272 | if (g->external_symbol_names.maybe_get(new_name) == nullptr) { | |
| 273 | return new_name; | |
| 274 | } | |
| 275 | } | |
| 276 | } | |
| 277 | ||
| 263 | 278 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 264 | 279 | if (fn_table_entry->llvm_value) |
| 265 | 280 | return fn_table_entry->llvm_value; |
| 266 | 281 | |
| 267 | Buf *symbol_name; | |
| 268 | if (!fn_table_entry->internal_linkage) { | |
| 269 | symbol_name = &fn_table_entry->symbol_name; | |
| 270 | } else { | |
| 271 | symbol_name = buf_sprintf("_%s", buf_ptr(&fn_table_entry->symbol_name)); | |
| 272 | } | |
| 282 | Buf *symbol_name = get_mangled_name(g, &fn_table_entry->symbol_name, !fn_table_entry->internal_linkage); | |
| 273 | 283 | |
| 274 | 284 | TypeTableEntry *fn_type = fn_table_entry->type_entry; |
| 275 | 285 | LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref; |
| ... | ... | @@ -3288,7 +3298,7 @@ static void do_code_gen(CodeGen *g) { |
| 3288 | 3298 | LLVMSetLinkage(global_value, LLVMExternalLinkage); |
| 3289 | 3299 | } else { |
| 3290 | 3300 | render_const_val(g, var->value); |
| 3291 | render_const_val_global(g, var->value, buf_ptr(&var->name)); | |
| 3301 | render_const_val_global(g, var->value, buf_ptr(get_mangled_name(g, &var->name, false))); | |
| 3292 | 3302 | global_value = var->value->llvm_global; |
| 3293 | 3303 | |
| 3294 | 3304 | if (var->linkage == VarLinkageExport) { |
test/run_tests.cpp+18-1| ... | ... | @@ -1631,7 +1631,7 @@ const foo = @import("foo.zig"); |
| 1631 | 1631 | export fn callPrivFunction() { |
| 1632 | 1632 | foo.privateFunction(); |
| 1633 | 1633 | } |
| 1634 | )SOURCE", 2, | |
| 1634 | )SOURCE", 2, | |
| 1635 | 1635 | ".tmp_source.zig:5:8: error: 'privateFunction' is private", |
| 1636 | 1636 | "foo.zig:2:1: note: declared here"); |
| 1637 | 1637 | |
| ... | ... | @@ -1828,6 +1828,23 @@ fn ptrEql(a: &[]const u8, b: &[]const u8) -> bool { |
| 1828 | 1828 | |
| 1829 | 1829 | export fn entry() -> usize { @sizeOf(@typeOf(foo)) } |
| 1830 | 1830 | )SOURCE", 1, ".tmp_source.zig:5:19: error: expected type '&[]const u8', found '&const []const u8'"); |
| 1831 | ||
| 1832 | { | |
| 1833 | TestCase *tc = add_compile_fail_case("export collision", R"SOURCE( | |
| 1834 | const foo = @import("foo.zig"); | |
| 1835 | ||
| 1836 | export fn bar() -> usize { | |
| 1837 | return foo.baz; | |
| 1838 | } | |
| 1839 | )SOURCE", 2, | |
| 1840 | "foo.zig:2:8: error: exported symbol collision: 'bar'", | |
| 1841 | ".tmp_source.zig:4:8: note: other symbol is here"); | |
| 1842 | ||
| 1843 | add_source_file(tc, "foo.zig", R"SOURCE( | |
| 1844 | export fn bar() {} | |
| 1845 | pub const baz = 1234; | |
| 1846 | )SOURCE"); | |
| 1847 | } | |
| 1831 | 1848 | } |
| 1832 | 1849 | |
| 1833 | 1850 | ////////////////////////////////////////////////////////////////////////////// |