autofree: fix string reassignment
							parent
							
								
									62cae1ba00
								
							
						
					
					
						commit
						0e8c7ca2e3
					
				|  | @ -1412,13 +1412,30 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { | |||
| 		else {} | ||||
| 	} | ||||
| 	// Free the old value assigned to this string var (only if it's `str = [new value]`)
 | ||||
| 	if g.pref.autofree && assign_stmt.op == .assign && assign_stmt.left_types.len == 1 && | ||||
| 		assign_stmt.left_types[0] == table.string_type && assign_stmt.left[0] is ast.Ident { | ||||
| 	mut af := g.pref.autofree && assign_stmt.op == .assign && assign_stmt.left_types.len == 1 && | ||||
| 		assign_stmt.left_types[0] == table.string_type && assign_stmt.left[0] is ast.Ident | ||||
| 	mut sref_name := '' | ||||
| 	if af { | ||||
| 		ident := assign_stmt.left[0] as ast.Ident | ||||
| 		if ident.name != '_' { | ||||
| 			/* | ||||
| 			g.write('string_free(&') | ||||
| 			g.expr(assign_stmt.left[0]) | ||||
| 			g.writeln('); // free str on re-assignment') | ||||
| 			*/ | ||||
| 			sref_name = '_sref$assign_stmt.pos.pos' | ||||
| 			g.write('string $sref_name = (') // TODO we are copying the entire string here, optimize
 | ||||
| 			// we can't just do `.str` since we need the extra data from the string struct
 | ||||
| 			// doing `&string` is also not an option since the stack memory with the data will be overwritten
 | ||||
| 			g.expr(assign_stmt.left[0]) | ||||
| 			g.writeln('); // free str on re-assignment2') | ||||
| 			defer { | ||||
| 				if af { | ||||
| 					g.writeln('string_free(&$sref_name);') | ||||
| 				} | ||||
| 			} | ||||
| 		} else { | ||||
| 			af = false | ||||
| 		} | ||||
| 	} | ||||
| 	// Autofree tmp arg vars
 | ||||
|  |  | |||
|  | @ -741,7 +741,7 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { | |||
| 		return | ||||
| 	} | ||||
| 	g.doing_autofree_tmp = true | ||||
| 	g.write('/* postgen */') | ||||
| 	// g.write('/* postgen */')
 | ||||
| 	scope := g.file.scope.innermost(node_pos) | ||||
| 	for _, obj in scope.objects { | ||||
| 		match mut obj { | ||||
|  | @ -770,7 +770,7 @@ fn (mut g Gen) autofree_call_postgen(node_pos int) { | |||
| 			else {} | ||||
| 		} | ||||
| 	} | ||||
| 	g.write('/* postgen end */') | ||||
| 	// g.write('/* postgen end */')
 | ||||
| 	g.doing_autofree_tmp = false | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| // This program is built and run via Valgrind to ensure there are no leaks with -autofree
 | ||||
| fn simple() { | ||||
| 	nums := [1, 2, 3] // local array must be freed
 | ||||
| 	println(nums) | ||||
|  | @ -64,8 +65,12 @@ fn str_inter() { | |||
| 
 | ||||
| fn str_replace() { | ||||
| 	mut s := 'hello world' | ||||
| 	s = s.replace('hello', 'hi') | ||||
| 	s = s.replace('hello', 'hi') // s can't be freed as usual before the assignment, since it's used in the right expr
 | ||||
| 	println(s) | ||||
| 	//
 | ||||
| 	mut s2 := 'aa' + 'bb' | ||||
| 	s2 = s2.replace('a', 'c') | ||||
| 	println(s2) | ||||
| 	/* | ||||
| 	r := s.replace('hello', 'hi') | ||||
| 	cloned := s.replace('hello', 'hi').clone() | ||||
|  | @ -85,8 +90,12 @@ fn str_replace2() { | |||
| } | ||||
| 
 | ||||
| fn reassign_str() { | ||||
| 	mut x := 'a' | ||||
| 	x = 'b' // nothing has to be freed here
 | ||||
| 	//
 | ||||
| 	mut s := 'a' + 'b' | ||||
| 	s = 'x' + 'y' // 'a' + 'b' must be freed before the re-assignment
 | ||||
| 	s = s + '!' // old s ref must be copied and freed after the assignment, since s is still used in the right expr
 | ||||
| } | ||||
| 
 | ||||
| fn match_expr() string { | ||||
|  | @ -212,12 +221,12 @@ fn free_inside_opt_block() { | |||
| fn main() { | ||||
| 	println('start') | ||||
| 	simple() | ||||
| 	reassign_str() | ||||
| 	str_tmp_expr() | ||||
| 	str_tmp_expr_advanced() | ||||
| 	str_tmp_expr_advanced_var_decl() | ||||
| 	str_inter() | ||||
| 	match_expr() | ||||
| 	reassign_str() | ||||
| 	optional_str() | ||||
| 	// optional_return()
 | ||||
| 	str_replace() | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue