Skip to content

Commit 8b1db3b

Browse files
committed
cgen: emit forward typedefs for struct types used in C extern function signatures
When -skip_unused is active, struct types referenced only in extern function declarations may not get their typedefs emitted, causing 'unknown type name' errors in the generated C. This restores the forward-declaration logic that was removed in 43fdf0f, ensuring types like main__Iwad_t are typedef'd before the extern prototypes that reference them (fixes C2V apps CI).
1 parent 4c44e6d commit 8b1db3b

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

vlib/v/gen/c/fn.v

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -675,6 +675,44 @@ fn (g &Gen) should_emit_c_extern_decl(node ast.FnDecl) bool {
675675
return false
676676
}
677677

678+
fn (mut g Gen) ensure_extern_sig_type_decls(node ast.FnDecl) {
679+
g.ensure_extern_sig_type_decl(node.return_type)
680+
for param in node.params {
681+
g.ensure_extern_sig_type_decl(param.typ)
682+
}
683+
}
684+
685+
fn (mut g Gen) ensure_extern_sig_type_decl(typ_ ast.Type) {
686+
if typ_ == 0 {
687+
return
688+
}
689+
typ := typ_.clear_option_and_result().set_nr_muls(0).clear_flags(.generic, .variadic)
690+
if typ == 0 {
691+
return
692+
}
693+
sym := g.table.sym(typ)
694+
if sym.is_builtin || sym.name in ['byte', 'i32', 'C.FILE'] {
695+
return
696+
}
697+
if sym.idx in g.table.used_features.used_syms {
698+
return
699+
}
700+
if sym.info is ast.Struct {
701+
if sym.language == .c && sym.cname.starts_with('C__') && !sym.info.is_anon {
702+
c_struct_name := sym.cname[3..]
703+
if c_struct_name != 'va_list' {
704+
if sym.info.is_typedef {
705+
g.typedefs.writeln('typedef struct ${c_struct_name} ${c_struct_name};')
706+
} else {
707+
g.typedefs.writeln('struct ${c_struct_name};')
708+
}
709+
}
710+
} else {
711+
g.typedefs.writeln('typedef struct ${sym.cname} ${sym.cname};')
712+
}
713+
}
714+
}
715+
678716
fn (mut g Gen) is_used_by_main(node ast.FnDecl) bool {
679717
$if trace_unused_by_main ? {
680718
defer(fn) {
@@ -837,6 +875,9 @@ fn (mut g Gen) fn_decl(node ast.FnDecl) {
837875
}
838876
if node.language == .c && (node.is_c_extern || g.should_emit_c_extern_decl(node)) {
839877
g.inside_c_extern = true
878+
if g.pref.skip_unused {
879+
g.ensure_extern_sig_type_decls(node)
880+
}
840881
}
841882

842883
g.gen_attrs(node.attrs)

0 commit comments

Comments
 (0)