mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
autofree: fix frees before returns
This commit is contained in:
parent
b9cbb4f177
commit
e86c6e024c
@ -4721,27 +4721,30 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||
if expr is ast.Ident {
|
||||
g.returned_var_name = expr.name
|
||||
}
|
||||
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
||||
}
|
||||
// free := g.is_autofree && !g.is_builtin_mod // node.exprs[0] is ast.CallExpr
|
||||
// Create a temporary variable for the return expression
|
||||
free := !g.is_builtin_mod // node.exprs[0] is ast.CallExpr
|
||||
mut gen_tmp_var := !g.is_builtin_mod // node.exprs[0] is ast.CallExpr
|
||||
mut tmp := ''
|
||||
if free {
|
||||
if gen_tmp_var {
|
||||
// `return foo(a, b, c)`
|
||||
// `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;`
|
||||
// Save return value in a temp var so that all args (a,b,c) can be freed
|
||||
// Don't use a tmp var if a variable is simply returned: `return x`
|
||||
if node.exprs[0] !is ast.Ident {
|
||||
tmp = g.new_tmp_var()
|
||||
g.write('/*tmp return var*/ ')
|
||||
g.write(g.typ(g.fn_decl.return_type))
|
||||
g.write(' ')
|
||||
g.write(tmp)
|
||||
g.write(' = ')
|
||||
} else {
|
||||
gen_tmp_var = false
|
||||
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
||||
g.write('return ')
|
||||
}
|
||||
} else {
|
||||
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
||||
g.write('return ')
|
||||
}
|
||||
if expr0.is_auto_deref_var() {
|
||||
@ -4755,10 +4758,11 @@ fn (mut g Gen) return_statement(node ast.Return) {
|
||||
} else {
|
||||
g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
|
||||
}
|
||||
if free {
|
||||
if gen_tmp_var {
|
||||
g.writeln(';')
|
||||
has_semicolon = true
|
||||
if tmp != '' {
|
||||
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
|
||||
g.write('return $tmp')
|
||||
has_semicolon = false
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import os
|
||||
import strings
|
||||
|
||||
// This program is built and run via Valgrind to ensure there are no leaks with -autofree
|
||||
fn simple() {
|
||||
@ -341,6 +342,12 @@ fn comp_if() {
|
||||
fn anon_fn() {
|
||||
}
|
||||
|
||||
fn return_sb_str() string {
|
||||
mut sb := strings.new_builder(100)
|
||||
sb.write_string('hello')
|
||||
return sb.str() // sb should be freed, but only after .str() is called
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println('start')
|
||||
simple()
|
||||
@ -364,6 +371,7 @@ fn main() {
|
||||
free_before_return()
|
||||
free_before_return_bool()
|
||||
free_before_break()
|
||||
s := return_sb_str()
|
||||
// free_map()
|
||||
// loop_map()
|
||||
free_array_except_returned_element()
|
||||
|
Loading…
Reference in New Issue
Block a user