Skip to content

Commit

Permalink
cgen: fix wrong cgen, when auto_heap var, is used as a closed over ar…
Browse files Browse the repository at this point in the history
…g in a closure (fix #20208) (#20566)
  • Loading branch information
shove70 committed Jan 17, 2024
1 parent c4b8036 commit 4c47bb5
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
14 changes: 13 additions & 1 deletion vlib/v/gen/c/fn.v
Expand Up @@ -509,8 +509,10 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
g.indent++
for var in node.inherited_vars {
mut has_inherited := false
mut is_ptr := false
if obj := node.decl.scope.find(var.name) {
if obj is ast.Var {
is_ptr = obj.typ.is_ptr()
if obj.has_inherited {
has_inherited = true
var_sym := g.table.sym(var.typ)
Expand Down Expand Up @@ -539,7 +541,17 @@ fn (mut g Gen) gen_anon_fn(mut node ast.AnonFn) {
} else if g.is_autofree && !var.is_mut && var_sym.kind == .string {
g.writeln('.${var.name} = string_clone(${var.name}),')
} else {
g.writeln('.${var.name} = ${var.name},')
mut is_auto_heap := false
if obj := node.decl.scope.parent.find(var.name) {
if obj is ast.Var {
is_auto_heap = !obj.is_stack_obj && obj.is_auto_heap
}
}
if is_auto_heap && !is_ptr {
g.writeln('.${var.name} = *${var.name},')
} else {
g.writeln('.${var.name} = ${var.name},')
}
}
}
}
Expand Down
30 changes: 30 additions & 0 deletions vlib/v/tests/closure_test.v
Expand Up @@ -268,3 +268,33 @@ fn test_array_string_and_map_as_closure_params_with_autofree() {
func()
assert true
}

// for issue 20208
// phenomenon: cgen fails when the closure arg is auto_heap and is not reference.
@[heap]
struct Abc {
value int
}

@[heap]
struct Container {
abc &Abc = unsafe { nil }
}

fn (mut c Container) m() fn () {
mut cr := &c
assert voidptr(c.abc) == voidptr(cr.abc)
f := fn [mut cr] () {
assert cr.abc.value == 1234
}
return f
}

fn test_auto_heap_var_and_non_ptr_as_closure_arg() {
mut c := &Container{
abc: &Abc{1234}
}
f := c.m()
f()
assert true
}

0 comments on commit 4c47bb5

Please sign in to comment.