Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -13512,7 +13512,18 @@ return ${cast_shared_struct_str};
}
iin_idx := already_generated_mwrappers[interface_index_name] - iinidx_minimum_base + 1
if g.pref.build_mode != .build_module {
sb.writeln('enum { ${interface_index_name} = ${iin_idx} };')
if g.pref.use_cache {
// With -usecache, modules like `builtin` are compiled separately
// in build_module mode, where the index is emitted as
// `extern const u32 ..._index;` and referenced. The main program
// must therefore provide a real, externally-linked definition
// (not a compile-time `enum` constant, which has no linker
// symbol), otherwise the reference is undefined at link time -
// e.g. `undefined symbol: _IError_None___index` on FreeBSD/clang.
sb.writeln('const u32 ${interface_index_name} = ${iin_idx};')
Comment thread
medvednikov marked this conversation as resolved.
Outdated
} else {
sb.writeln('enum { ${interface_index_name} = ${iin_idx} };')
}
} else {
sb.writeln('extern const u32 ${interface_index_name};')
}
Expand Down
39 changes: 39 additions & 0 deletions vlib/v/tests/usecache_interface_index_symbol_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import os

const vexe = @VEXE

// Regression test for https://github.com/vlang/v/issues/27330
//
// With -usecache, modules like `builtin` are compiled separately in
// build_module mode, where the interface type-table index is emitted as
// `extern const u32 ..._index;` and referenced. The main program must therefore
// provide a real, externally-linked `const u32 ..._index = N;` definition - a
// compile-time `enum` constant has no linker symbol, so the reference would be
// undefined at link time (e.g. `undefined symbol: _IError_None___index` on
// FreeBSD/clang).
fn test_usecache_interface_index_is_real_symbol() {
tmp_dir := os.join_path(os.vtmp_dir(), 'v_issue_27330')
os.mkdir_all(tmp_dir) or { panic(err) }
defer {
os.rmdir_all(tmp_dir) or {}
}
source_path := os.join_path(tmp_dir, 'issue_27330.v')
os.write_file(source_path, "fn main() {\n\tprintln('hello world')\n}\n") or { panic(err) }

// -o - dumps the generated C of the main program to stdout.
res := os.execute('${os.quoted_path(vexe)} -usecache -o - ${os.quoted_path(source_path)}')
if res.exit_code != 0 {
panic(res.output)
}
// The index must be a real (externally-linked) definition, not a bare enum.
assert res.output.contains('const u32 _IError_None___index =')
assert !res.output.contains('enum { _IError_None___index =')

// Sanity check: without -usecache the compile-time enum form is kept (it is
// the tcc-friendly form and needs no external symbol in a single build).
res2 := os.execute('${os.quoted_path(vexe)} -o - ${os.quoted_path(source_path)}')
if res2.exit_code != 0 {
panic(res2.output)
}
assert res2.output.contains('enum { _IError_None___index =')
}
Loading