Skip to content

Commit

Permalink
cgen: fix several issues with autofree(fix vlang#20635)
Browse files Browse the repository at this point in the history
  • Loading branch information
shove70 committed Jan 26, 2024
1 parent 8714233 commit 624a3ed
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 10 deletions.
25 changes: 15 additions & 10 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -2873,7 +2873,8 @@ fn (mut g Gen) get_ternary_name(name string) string {
}

fn (mut g Gen) gen_clone_assignment(val ast.Expr, typ ast.Type, add_eq bool) bool {
if val !in [ast.Ident, ast.SelectorExpr] {
if val !in [ast.Ident, ast.SelectorExpr, ast.CallExpr, ast.MatchExpr, ast.IfExpr, ast.IndexExpr,
ast.ParExpr, ast.UnsafeExpr] {
return false
}
right_sym := g.table.sym(typ)
Expand Down Expand Up @@ -2978,6 +2979,11 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
// TODO: free options
continue
}
is_result := obj.typ.has_flag(.result)
if is_result {
// TODO: free result
continue
}
g.autofree_variable(obj)
}
else {}
Expand Down Expand Up @@ -5348,6 +5354,14 @@ fn (mut g Gen) return_stmt(node ast.Return) {
node.types[0].has_flag(.option)
}
}
// autofree before `return`
// set free_parent_scopes to true, since all variables defined in parent
// scopes need to be freed before the return
if g.is_autofree {
if expr0 is ast.Ident {
g.returned_var_name = expr0.name
}
}
if fn_return_is_option && !expr_type_is_opt && return_sym.name != c.option_name {
styp := g.base_type(fn_ret_type)
g.writeln('${ret_typ} ${tmpvar};')
Expand Down Expand Up @@ -5408,15 +5422,6 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln('return ${tmpvar};')
return
}
// autofree before `return`
// set free_parent_scopes to true, since all variables defined in parent
// scopes need to be freed before the return
if g.is_autofree {
expr := node.exprs[0]
if expr is ast.Ident {
g.returned_var_name = expr.name
}
}
// free := g.is_autofree && !g.is_builtin_mod // node.exprs[0] is ast.CallExpr
// Create a temporary variable for the return expression
if use_tmp_var || !g.is_builtin_mod {
Expand Down
58 changes: 58 additions & 0 deletions vlib/v/tests/autofree_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// vtest vflags: -autofree

fn return_array_with_result() ![]int {
mut arr := []int{}
arr << 123
return arr
}

fn return_array_with_option() ?[]int {
mut arr := []int{}
arr << 123
return arr
}

fn return_strng(s string) string {
return s
}

fn test_main() {
arr1 := return_array_with_result()!
assert arr1 == [123]
arr2 := return_array_with_option()?
assert arr2 == [123]

// test ident
str1 := '${'123'}abc'
str2 := str1
assert str2 == '123abc'

// test CallExpr
str3 := return_strng(str1)
assert str3 == '123abc'

// test MatchExpr
str4 := match true {
true {
str1
}
else {
str1
}
}
assert str4 == '123abc'

// test IfExpr
str5 := if true { str1 } else { str1 }
assert str5 == '123abc'

// test ParExpr
// vfmt off
str6 := (str1)
// vfmt on
assert str6 == '123abc'

// test UnsafeExpr
str7 := unsafe { str1 }
assert str7 == '123abc'
}

0 comments on commit 624a3ed

Please sign in to comment.