This commit is contained in:
Felipe Pena 2025-08-30 09:58:41 -03:00
parent 24f91280d9
commit 7f402b3e1c
3 changed files with 28 additions and 10 deletions

View file

@ -62,7 +62,7 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
match obj { match obj {
ast.Var { ast.Var {
g.trace_autofree('// var "${obj.name}" var.pos=${obj.pos.pos} var.line_nr=${obj.pos.line_nr}') g.trace_autofree('// var "${obj.name}" var.pos=${obj.pos.pos} var.line_nr=${obj.pos.line_nr}')
if obj.name == g.returned_var_name { if obj.name in g.returned_var_names {
g.print_autofree_var(obj, 'returned from function') g.print_autofree_var(obj, 'returned from function')
g.trace_autofree('// skipping returned var') g.trace_autofree('// skipping returned var')
continue continue
@ -247,3 +247,17 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
} }
g.autofree_scope_stmts << af.str() g.autofree_scope_stmts << af.str()
} }
fn (mut g Gen) detect_used_var_on_return(expr ast.Expr) {
match expr {
ast.Ident {
g.returned_var_names[expr.name] = true
}
ast.StructInit {
for field_expr in expr.init_fields {
g.detect_used_var_on_return(field_expr.expr)
}
}
else {}
}
}

View file

@ -231,11 +231,11 @@ mut:
// where an aggregate (at least two types) is generated // where an aggregate (at least two types) is generated
// sum type deref needs to know which index to deref because unions take care of the correct field // sum type deref needs to know which index to deref because unions take care of the correct field
aggregate_type_idx int aggregate_type_idx int
arg_no_auto_deref bool // smartcast must not be dereferenced arg_no_auto_deref bool // smartcast must not be dereferenced
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned returned_var_names map[string]bool // to detect that vars doesn't need to be freed since it's being returned
infix_left_var_name string // a && if expr infix_left_var_name string // a && if expr
curr_var_name []string // curr var name on assignment curr_var_name []string // curr var name on assignment
called_fn_name string called_fn_name string
timers &util.Timers = util.get_timers() timers &util.Timers = util.get_timers()
force_main_console bool // true when @[console] used on fn main() force_main_console bool // true when @[console] used on fn main()
@ -6241,6 +6241,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));') g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));')
} }
g.write_defer_stmts_when_needed() g.write_defer_stmts_when_needed()
if g.is_autofree {
g.detect_used_var_on_return(expr0)
}
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true) g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
g.writeln('return ${tmpvar};') g.writeln('return ${tmpvar};')
return return
@ -6286,6 +6289,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));') g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));')
} }
g.write_defer_stmts_when_needed() g.write_defer_stmts_when_needed()
if g.is_autofree {
g.detect_used_var_on_return(expr0)
}
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true) g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
g.writeln('return ${tmpvar};') g.writeln('return ${tmpvar};')
return return
@ -6294,9 +6300,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
// set free_parent_scopes to true, since all variables defined in parent // set free_parent_scopes to true, since all variables defined in parent
// scopes need to be freed before the return // scopes need to be freed before the return
if g.is_autofree { if g.is_autofree {
if expr0 is ast.Ident { g.detect_used_var_on_return(expr0)
g.returned_var_name = expr0.name
}
if !use_tmp_var && !g.is_builtin_mod { if !use_tmp_var && !g.is_builtin_mod {
use_tmp_var = expr0 is ast.CallExpr use_tmp_var = expr0 is ast.CallExpr
} }

View file

@ -196,7 +196,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
} }
*/ */
g.returned_var_name = '' g.returned_var_names.clear()
old_g_autofree := g.is_autofree old_g_autofree := g.is_autofree
if node.is_manualfree { if node.is_manualfree {
g.is_autofree = false g.is_autofree = false