diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 34f0f35929..36e4d8a1a2 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -287,7 +287,7 @@ pub mut: return_type table.Type should_be_skipped bool generic_type table.Type // TODO array, to support multiple types - autofree_pregen string + // autofree_pregen string // autofree_vars []AutofreeArgVar // autofree_vars_ids []int } @@ -593,20 +593,20 @@ pub: pub struct ForInStmt { pub: - key_var string - val_var string - cond Expr - is_range bool - high Expr // `10` in `for i in 0..10 {` - stmts []Stmt - pos token.Position + key_var string + val_var string + cond Expr + is_range bool + high Expr // `10` in `for i in 0..10 {` + stmts []Stmt + pos token.Position val_is_mut bool // `for mut val in vals {` means that modifying `val` will modify the array - // and the array cannot be indexed inside the loop pub mut: - key_type table.Type - val_type table.Type - cond_type table.Type - kind table.Kind // array/map/string + // and the array cannot be indexed inside the loop + key_type table.Type + val_type table.Type + cond_type table.Type + kind table.Kind // array/map/string } pub struct ForCStmt { @@ -989,11 +989,7 @@ pub fn (expr Expr) position() token.Position { AnonFn { return expr.decl.pos } - ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, CharLiteral, - Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr, - IntegerLiteral, MapInit, MatchExpr, None, PostfixExpr, PrefixExpr, - SelectExpr, SelectorExpr, SizeOf, StringLiteral, StringInterLiteral, - StructInit, Likely { + ArrayInit, AsCast, Assoc, BoolLiteral, CallExpr, CastExpr, CharLiteral, Comment, EnumVal, FloatLiteral, Ident, IfExpr, IndexExpr, IntegerLiteral, MapInit, MatchExpr, None, PostfixExpr, PrefixExpr, SelectExpr, SelectorExpr, SizeOf, StringLiteral, StringInterLiteral, StructInit, Likely { return expr.pos } InfixExpr { @@ -1042,11 +1038,15 @@ pub fn (expr Expr) is_expr() bool { } // check if stmt can be an expression in C -pub fn (stmt Stmt) check_c_expr()? { +pub fn (stmt Stmt) check_c_expr() ? { match stmt { - AssignStmt {return} + AssignStmt { + return + } ExprStmt { - if stmt.expr.is_expr() {return} + if stmt.expr.is_expr() { + return + } return error('unsupported statement (`${typeof(stmt.expr)}`)') } else {} @@ -1056,10 +1056,7 @@ pub fn (stmt Stmt) check_c_expr()? { pub fn (stmt Stmt) position() token.Position { match stmt { - AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, - ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl { - return stmt.pos - } + AssertStmt, AssignStmt, Block, ConstDecl, EnumDecl, ExprStmt, FnDecl, ForCStmt, ForInStmt, ForStmt, Import, Return, StructDecl { return stmt.pos } /* Attr {} BranchStmt {} diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 79bc5626fb..9176234b28 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -985,12 +985,16 @@ fn (mut g Gen) stmt(node ast.Stmt) { } ast.Return { g.write_defer_stmts_when_needed() + af := g.pref.autofree && node.exprs.len > 0 && node.exprs[0] is ast.CallExpr && !g.is_builtin_mod if g.pref.autofree { g.writeln('// ast.Return free') + if af { + g.autofree_call_pregen(node.exprs[0] as ast.CallExpr) + } // g.autofree_scope_vars(node.pos.pos) g.write_autofree_stmts_when_needed(node) } - g.return_statement(node) + g.return_statement(node, af) } ast.SqlStmt { g.sql_stmt(node) @@ -3458,7 +3462,7 @@ fn (g &Gen) expr_is_multi_return_call(expr ast.Expr) bool { } } -fn (mut g Gen) return_statement(node ast.Return) { +fn (mut g Gen) return_statement(node ast.Return, af bool) { g.write_v_source_line_info(node.pos) if node.exprs.len > 0 { // skip `retun $vweb.html()` @@ -3496,6 +3500,10 @@ fn (mut g Gen) return_statement(node ast.Return) { g.write('Option $tmp = ') g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type) g.writeln(';') + if af { + // free the tmp arg expr if we have one before the return + g.autofree_call_postgen() + } styp := g.typ(g.fn_decl.return_type) g.writeln('return *($styp*)&$tmp;') return diff --git a/vlib/v/tests/valgrind/1.strings_and_arrays.v b/vlib/v/tests/valgrind/1.strings_and_arrays.v index 8082812a07..316b5f8799 100644 --- a/vlib/v/tests/valgrind/1.strings_and_arrays.v +++ b/vlib/v/tests/valgrind/1.strings_and_arrays.v @@ -109,6 +109,20 @@ fn optional_str() { println(pos + 1) } +fn return_error_with_freed_expr() ?string { + if true { + msg := 'oops' + return error('hm $msg') + } + return 'ok' +} + +fn optional_return() { + return_error_with_freed_expr() or { + return + } +} + fn tt() { // time.parse_rfc2822('1234') } @@ -123,6 +137,7 @@ fn main() { match_expr() reassign_str() optional_str() + optional_return() // str_replace() println('end') }