mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
parent
cb2756e39c
commit
9fb8aae2d7
7 changed files with 53 additions and 10 deletions
|
@ -62,7 +62,7 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
|
||||||
match obj {
|
match obj {
|
||||||
ast.Var {
|
ast.Var {
|
||||||
g.trace_autofree('// var "${obj.name}" var.pos=${obj.pos.pos} var.line_nr=${obj.pos.line_nr}')
|
g.trace_autofree('// var "${obj.name}" var.pos=${obj.pos.pos} var.line_nr=${obj.pos.line_nr}')
|
||||||
if obj.name == g.returned_var_name {
|
if obj.name in g.returned_var_names {
|
||||||
g.print_autofree_var(obj, 'returned from function')
|
g.print_autofree_var(obj, 'returned from function')
|
||||||
g.trace_autofree('// skipping returned var')
|
g.trace_autofree('// skipping returned var')
|
||||||
continue
|
continue
|
||||||
|
@ -247,3 +247,17 @@ fn (mut g Gen) autofree_var_call(free_fn_name string, v ast.Var) {
|
||||||
}
|
}
|
||||||
g.autofree_scope_stmts << af.str()
|
g.autofree_scope_stmts << af.str()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn (mut g Gen) detect_used_var_on_return(expr ast.Expr) {
|
||||||
|
match expr {
|
||||||
|
ast.Ident {
|
||||||
|
g.returned_var_names[expr.name] = true
|
||||||
|
}
|
||||||
|
ast.StructInit {
|
||||||
|
for field_expr in expr.init_fields {
|
||||||
|
g.detect_used_var_on_return(field_expr.expr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -231,11 +231,11 @@ mut:
|
||||||
// where an aggregate (at least two types) is generated
|
// where an aggregate (at least two types) is generated
|
||||||
// sum type deref needs to know which index to deref because unions take care of the correct field
|
// sum type deref needs to know which index to deref because unions take care of the correct field
|
||||||
aggregate_type_idx int
|
aggregate_type_idx int
|
||||||
arg_no_auto_deref bool // smartcast must not be dereferenced
|
arg_no_auto_deref bool // smartcast must not be dereferenced
|
||||||
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
||||||
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned
|
returned_var_names map[string]bool // to detect that vars doesn't need to be freed since it's being returned
|
||||||
infix_left_var_name string // a && if expr
|
infix_left_var_name string // a && if expr
|
||||||
curr_var_name []string // curr var name on assignment
|
curr_var_name []string // curr var name on assignment
|
||||||
called_fn_name string
|
called_fn_name string
|
||||||
timers &util.Timers = util.get_timers()
|
timers &util.Timers = util.get_timers()
|
||||||
force_main_console bool // true when @[console] used on fn main()
|
force_main_console bool // true when @[console] used on fn main()
|
||||||
|
@ -6241,6 +6241,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));')
|
g.writeln(' }, (${option_name}*)(&${tmpvar}), sizeof(${styp}));')
|
||||||
}
|
}
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
|
if g.is_autofree {
|
||||||
|
g.detect_used_var_on_return(expr0)
|
||||||
|
}
|
||||||
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.writeln('return ${tmpvar};')
|
g.writeln('return ${tmpvar};')
|
||||||
return
|
return
|
||||||
|
@ -6286,6 +6289,9 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));')
|
g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));')
|
||||||
}
|
}
|
||||||
g.write_defer_stmts_when_needed()
|
g.write_defer_stmts_when_needed()
|
||||||
|
if g.is_autofree {
|
||||||
|
g.detect_used_var_on_return(expr0)
|
||||||
|
}
|
||||||
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.writeln('return ${tmpvar};')
|
g.writeln('return ${tmpvar};')
|
||||||
return
|
return
|
||||||
|
@ -6294,9 +6300,7 @@ fn (mut g Gen) return_stmt(node ast.Return) {
|
||||||
// set free_parent_scopes to true, since all variables defined in parent
|
// set free_parent_scopes to true, since all variables defined in parent
|
||||||
// scopes need to be freed before the return
|
// scopes need to be freed before the return
|
||||||
if g.is_autofree {
|
if g.is_autofree {
|
||||||
if expr0 is ast.Ident {
|
g.detect_used_var_on_return(expr0)
|
||||||
g.returned_var_name = expr0.name
|
|
||||||
}
|
|
||||||
if !use_tmp_var && !g.is_builtin_mod {
|
if !use_tmp_var && !g.is_builtin_mod {
|
||||||
use_tmp_var = expr0 is ast.CallExpr
|
use_tmp_var = expr0 is ast.CallExpr
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ fn (mut g Gen) gen_fn_decl(node &ast.FnDecl, skip bool) {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
g.returned_var_name = ''
|
g.returned_var_names.clear()
|
||||||
old_g_autofree := g.is_autofree
|
old_g_autofree := g.is_autofree
|
||||||
if node.is_manualfree {
|
if node.is_manualfree {
|
||||||
g.is_autofree = false
|
g.is_autofree = false
|
||||||
|
|
9
vlib/v/gen/c/testdata/autofree_toml.c.must_have
vendored
Normal file
9
vlib/v/gen/c/testdata/autofree_toml.c.must_have
vendored
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
_result_toml__scanner__Scanner_ptr toml__scanner__new_scanner(toml__scanner__Config config) {
|
||||||
|
_result_toml__scanner__Scanner_ptr _t3 = {0};
|
||||||
|
_result_ok(&(toml__scanner__Scanner*[]) { s }, (_result*)(&_t3), sizeof(toml__scanner__Scanner*));
|
||||||
|
return _t3;
|
||||||
|
}
|
||||||
|
toml__ast__Quoted toml__parser__Parser_quoted(toml__parser__Parser* p) {
|
||||||
|
return ((toml__ast__Quoted){.text = string_clone_static(lit),.pos = toml__token__Token_pos(&p->tok),.is_multiline = is_multiline,.quote = quote,});
|
||||||
|
}
|
||||||
|
|
0
vlib/v/gen/c/testdata/autofree_toml.out
vendored
Normal file
0
vlib/v/gen/c/testdata/autofree_toml.out
vendored
Normal file
15
vlib/v/gen/c/testdata/autofree_toml.vv
vendored
Normal file
15
vlib/v/gen/c/testdata/autofree_toml.vv
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// vtest vflags: -autofree
|
||||||
|
import toml
|
||||||
|
import os
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
config_fname := 'config.toml'
|
||||||
|
tab_title := 'test tab title'
|
||||||
|
if !os.exists(config_fname) {
|
||||||
|
mut f := os.create(config_fname) or { panic(err) }
|
||||||
|
f.writeln('tab_title = "${tab_title}"') or { panic(err) }
|
||||||
|
f.close()
|
||||||
|
}
|
||||||
|
doc := toml.parse_file(config_fname) or { panic(err) }
|
||||||
|
assert doc.value('tab_title').string() == tab_title
|
||||||
|
}
|
|
@ -398,6 +398,7 @@ fn advanced_options() {
|
||||||
s2 := parse_header1('foo:bar') or { return }
|
s2 := parse_header1('foo:bar') or { return }
|
||||||
_ := s.len + s2.len // avoid warning for unused variables
|
_ := s.len + s2.len // avoid warning for unused variables
|
||||||
// TODO: fix -autofree, so that it adds this free automatically:
|
// TODO: fix -autofree, so that it adds this free automatically:
|
||||||
|
unsafe { s.free() }
|
||||||
unsafe { s2.free() }
|
unsafe { s2.free() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue