autofree: fix free before return
							parent
							
								
									88097125f7
								
							
						
					
					
						commit
						4e62bc0b81
					
				| 
						 | 
				
			
			@ -4539,7 +4539,7 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
			
		|||
			styp := g.typ(g.fn_decl.return_type)
 | 
			
		||||
			g.writeln('return ($styp){0};')
 | 
			
		||||
		} else {
 | 
			
		||||
			if g.is_autofree && !g.is_builtin_mod {
 | 
			
		||||
			if g.is_autofree {
 | 
			
		||||
				g.writeln('// free before return (no values returned)')
 | 
			
		||||
				g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -4680,13 +4680,24 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
			
		|||
			g.writeln('return $opt_tmp;')
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		// autofree before `return`
 | 
			
		||||
		// set free_parent_scopes to true, since all variables defined in parent
 | 
			
		||||
		// scopes need to be freed before the return
 | 
			
		||||
		if g.is_autofree {
 | 
			
		||||
			expr := node.exprs[0]
 | 
			
		||||
			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 tmp := ''
 | 
			
		||||
		if free {
 | 
			
		||||
			// `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 it all args (a,b,c) can be freed
 | 
			
		||||
			// 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()
 | 
			
		||||
| 
						 | 
				
			
			@ -4712,18 +4723,8 @@ fn (mut g Gen) return_statement(node ast.Return) {
 | 
			
		|||
			g.expr_with_cast(node.exprs[0], node.types[0], g.fn_decl.return_type)
 | 
			
		||||
		}
 | 
			
		||||
		if free {
 | 
			
		||||
			expr := node.exprs[0]
 | 
			
		||||
			if expr is ast.Ident {
 | 
			
		||||
				g.returned_var_name = expr.name
 | 
			
		||||
			}
 | 
			
		||||
			g.writeln(';')
 | 
			
		||||
			has_semicolon = true
 | 
			
		||||
			// autofree before `return`
 | 
			
		||||
			// set free_parent_scopes to true, since all variables defined in parent
 | 
			
		||||
			// scopes need to be freed before the return
 | 
			
		||||
			if g.pref.autofree {
 | 
			
		||||
				g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
 | 
			
		||||
			}
 | 
			
		||||
			if tmp != '' {
 | 
			
		||||
				g.write('return $tmp')
 | 
			
		||||
				has_semicolon = false
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -318,6 +318,11 @@ fn get_user() User {
 | 
			
		|||
	return user
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn get_user2() User {
 | 
			
		||||
	users := [User{'Peter', 25}, User{'Alice', 21}]
 | 
			
		||||
	return users[0] // has to be cloned, since `users` are going to be freed at the end of the function
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
fn string_array_get() {
 | 
			
		||||
	s := ['a', 'b', 'c']
 | 
			
		||||
	x := s[0]
 | 
			
		||||
| 
						 | 
				
			
			@ -361,7 +366,7 @@ fn main() {
 | 
			
		|||
	free_before_break()
 | 
			
		||||
	// free_map()
 | 
			
		||||
	// loop_map()
 | 
			
		||||
	// free_array_except_returned_element()
 | 
			
		||||
	free_array_except_returned_element()
 | 
			
		||||
	println('end')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue