Skip to content

Commit 4c23b0e

Browse files
committed
cgen: cast fix
1 parent 2c8e8f0 commit 4c23b0e

2 files changed

Lines changed: 38 additions & 12 deletions

File tree

vlib/v/gen/c/fn.v

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5682,6 +5682,20 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type_ ast.Type, lang a
56825682
g.expected_arg_mut = old_expected_arg_mut
56835683
}
56845684
exp_sym := g.table.sym(expected_type)
5685+
// Cast function pointer arguments when the expected and actual types differ.
5686+
// V's checker allows coercing function types (e.g. Renderer* → voidptr in callbacks),
5687+
// but C compilers with -Werror=incompatible-pointer-types reject the mismatch.
5688+
// Only cast for V language calls with named function type aliases (not anonymous fn types).
5689+
if exp_sym.kind == .function && arg_sym.kind == .function && !arg.is_mut && lang == .v
5690+
&& !exp_sym.name.starts_with('fn ') {
5691+
exp_styp := g.styp(expected_type)
5692+
arg_styp := g.styp(arg_typ)
5693+
if exp_styp != arg_styp {
5694+
g.write('(${exp_styp})')
5695+
g.expr(arg.expr)
5696+
return
5697+
}
5698+
}
56855699
if arg.is_mut && exp_sym.kind in [.interface, .sum_type] {
56865700
expected_wrap_type := if expected_type.is_ptr() {
56875701
expected_type.deref()

vlib/v/gen/c/struct.v

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -897,20 +897,32 @@ fn (mut g Gen) struct_init_field(sfield ast.StructInitField, language ast.Langua
897897
&& g.cur_struct_init_typ != 0 {
898898
struct_sym := g.table.sym(g.cur_struct_init_typ)
899899
if struct_sym.info is ast.Struct {
900-
for f in struct_sym.info.fields {
901-
if f.name == sfield.name {
902-
// Only cast named function type aliases (e.g. ThreadCB),
903-
// not anonymous function types from generic structs which
904-
// may generate non-existent type names.
905-
fsym := g.table.sym(f.typ)
906-
if !fsym.name.starts_with('fn ') {
907-
field_styp := g.styp(f.typ)
908-
expr_styp := g.styp(sfield.typ)
909-
if field_styp != expr_styp {
910-
g.write('(${field_styp})')
900+
if struct_sym.info.is_typedef {
901+
// For @[typedef] C structs, the actual C field types may differ
902+
// from V's declarations (e.g. C has `const char*` but V uses `char*`).
903+
// Use __typeof__ to cast to the actual C struct field type.
904+
c_struct_name := if struct_sym.cname.starts_with('C__') {
905+
struct_sym.cname[3..]
906+
} else {
907+
struct_sym.cname
908+
}
909+
g.write('(__typeof__(((${c_struct_name}){}).${sfield.name}))')
910+
} else {
911+
for f in struct_sym.info.fields {
912+
if f.name == sfield.name {
913+
// Only cast named function type aliases (e.g. ThreadCB),
914+
// not anonymous function types from generic structs which
915+
// may generate non-existent type names.
916+
fsym := g.table.sym(f.typ)
917+
if !fsym.name.starts_with('fn ') {
918+
field_styp := g.styp(f.typ)
919+
expr_styp := g.styp(sfield.typ)
920+
if field_styp != expr_styp {
921+
g.write('(${field_styp})')
922+
}
911923
}
924+
break
912925
}
913-
break
914926
}
915927
}
916928
}

0 commit comments

Comments
 (0)