From 9fbea31f476e40908f12279c5e6ff741e7d54bcf Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 6 Sep 2020 13:02:29 +0200 Subject: [PATCH] autofree: fix exprs N levels deep --- vlib/v/ast/ast.v | 2 +- vlib/v/gen/cgen.v | 15 +++++++++------ vlib/v/gen/fn.v | 7 ++++--- vlib/v/gen/str.v | 6 ++++-- vlib/v/tests/valgrind/1.strings_and_arrays.v | 2 +- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 4c7310dd65..ddc3340046 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -307,7 +307,7 @@ pub: comments []Comment pub mut: typ table.Type - is_tmp_autofree bool // for autofree + is_tmp_autofree bool // tmp_name string // for autofree } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index edcfb3f989..8c520e4b99 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -99,7 +99,7 @@ mut: sql_side SqlExprSide // left or right, to distinguish idents in `name == name` inside_vweb_tmpl bool inside_return bool - strs_to_free string + strs_to_free []string // strings.Builder inside_call bool has_main bool inside_const bool @@ -725,18 +725,21 @@ fn (mut g Gen) write_v_source_line_info(pos token.Position) { fn (mut g Gen) stmt(node ast.Stmt) { g.stmt_path_pos << g.out.len - /* defer { // If we have temporary string exprs to free after this statement, do it. e.g.: // `foo('a' + 'b')` => `tmp := 'a' + 'b'; foo(tmp); string_free(&tmp);` if g.pref.autofree { - if g.strs_to_free != '' { - g.writeln(g.strs_to_free) - g.strs_to_free = '' + if g.strs_to_free.len != 0 { + g.writeln('// strs_to_free:') + for s in g.strs_to_free { + g.writeln(s) + } + g.strs_to_free = [] + // s := g.strs_to_free.str() + // g.strs_to_free.free() } } } - */ // println('cgen.stmt()') // g.writeln('//// stmt start') match node { diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 3a2414b318..22bc7ccca0 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -632,15 +632,16 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { // g.write(cur_line + ' /* cur line*/') // g.write(tmp) // Now free the tmp arg vars right after the function call - g.writeln(';') + g.strs_to_free << (';') for i, arg in node.args { if arg.is_tmp_autofree { fn_name := node.name.replace('.', '_') tmp := '_tt${g.tmp_count2}_arg_expr_${fn_name}_$i' - g.writeln('string_free(&$tmp);') + g.strs_to_free << ('string_free(&$tmp);') + // g.writeln('string_free(&$tmp);') } } - g.writeln('') + // g.writeln('') } } diff --git a/vlib/v/gen/str.v b/vlib/v/gen/str.v index deb5251648..6e77870727 100644 --- a/vlib/v/gen/str.v +++ b/vlib/v/gen/str.v @@ -194,11 +194,12 @@ fn (mut g Gen) string_inter_literal_sb_optimized(call_expr ast.CallExpr) { fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { mut cur_line := '' mut tmp := '' - free := !g.pref.experimental && g.pref.autofree && g.inside_call && !g.inside_return && + free := false && !g.pref.experimental && g.pref.autofree && g.inside_call && !g.inside_return && g.inside_ternary == 0 && !g.inside_const // && g.cur_fn != 0 && // g.cur_fn.name != '' - if free { + /* + if false && free { // Save the string expr in a temporary variable, so that it can be removed after the call. tmp = g.new_tmp_var() /* @@ -214,6 +215,7 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { g.write('string $tmp = ') g.strs_to_free += 'string_free(&$tmp); /*tmp str*/' } + */ g.write('_STR("') // Build the string with % mut end_string := false diff --git a/vlib/v/tests/valgrind/1.strings_and_arrays.v b/vlib/v/tests/valgrind/1.strings_and_arrays.v index d255fd0b45..f2b03716c7 100644 --- a/vlib/v/tests/valgrind/1.strings_and_arrays.v +++ b/vlib/v/tests/valgrind/1.strings_and_arrays.v @@ -25,7 +25,7 @@ fn handle_int(n int) { fn str_tmp_expr() { println('a' + 'b') // tmp expression result must be freed handle_strings('c' + 'd', 'e' + 'f') // multiple tmp expressions must be freed - // handle_int(handle_strings('x' + 'y', 'f')) // exprs 2 levels deep must bee freed + handle_int(handle_strings('x' + 'y', 'f')) // exprs 2 levels deep must bee freed } struct Foo {