autofree: more `return` fixes

pull/7137/head
Alexander Medvednikov 2020-12-04 20:44:33 +01:00
parent 6a47deb3f8
commit f14bd10c00
2 changed files with 22 additions and 12 deletions

View File

@ -2089,6 +2089,7 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
continue continue
} }
if obj.is_or { if obj.is_or {
g.writeln('// skipping `or{}` var "$obj.name"')
// Skip vars inited with the `or {}`, since they are generated // Skip vars inited with the `or {}`, since they are generated
// after the or block in C. // after the or block in C.
continue continue
@ -4051,12 +4052,16 @@ fn (mut g Gen) return_statement(node ast.Return) {
// `return foo(a, b, c)` // `return foo(a, b, c)`
// `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;` // `tmp := foo(a, b, c); free(a); free(b); free(c); return tmp;`
// Save return value in a temp var so that it all args (a,b,c) can be freed // Save return value in a temp var so that it all args (a,b,c) can be freed
tmp = g.new_tmp_var() // Don't use a tmp var if a variable is simply returned: `return x`
g.write(g.typ(g.fn_decl.return_type)) if node.exprs[0] !is ast.Ident {
g.write(' ') tmp = g.new_tmp_var()
g.write(tmp) g.write(g.typ(g.fn_decl.return_type))
g.write(' = ') g.write(' ')
// g.write('return $tmp;') g.write(tmp)
g.write(' = ')
} else {
g.write('return ')
}
} else { } else {
g.write('return ') g.write('return ')
} }
@ -4069,16 +4074,21 @@ fn (mut g Gen) return_statement(node ast.Return) {
g.write(')') g.write(')')
} }
if free { if free {
g.writeln('; // free tmp exprs')
// autofree before `return`
// set free_parent_scopes to true, since all variables defined in parent
// scopes need to be freed before the return
expr := node.exprs[0] expr := node.exprs[0]
if expr is ast.Ident { if expr is ast.Ident {
g.returned_var_name = expr.name g.returned_var_name = expr.name
} }
if tmp != '' {
g.writeln('; // free tmp exprs + all vars before return')
}
g.writeln(';')
// autofree before `return`
// set free_parent_scopes to true, since all variables defined in parent
// scopes need to be freed before the return
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.write('return $tmp') if tmp != '' {
g.write('return $tmp')
}
} }
} else { // if node.exprs.len == 0 { } else { // if node.exprs.len == 0 {
println('this should never happen') println('this should never happen')

View File

@ -148,7 +148,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
// Set correct variable position (after the or block) // Set correct variable position (after the or block)
// so that autofree doesn't free it in cgen before // so that autofree doesn't free it in cgen before
// it's declared. (`Or` variables are declared after the or block). // it's declared. (`Or` variables are declared after the or block).
if r0.or_block.pos.pos > 0 { if r0.or_block.pos.pos > 0 && r0.or_block.stmts.len > 0 {
v.is_or = true v.is_or = true
// v.pos = r0.or_block.pos. // v.pos = r0.or_block.pos.
} }