diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 8922399636..e93007a118 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -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 } diff --git a/vlib/v/tests/valgrind/1.strings_and_arrays.v b/vlib/v/tests/valgrind/1.strings_and_arrays.v index 0609361199..f0647bb632 100644 --- a/vlib/v/tests/valgrind/1.strings_and_arrays.v +++ b/vlib/v/tests/valgrind/1.strings_and_arrays.v @@ -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()