Skip to content

Commit 0dbbed7

Browse files
authored
cgen,autofree: fix method chaining generating invalid c code (fix #9094) (#25315)
1 parent d2174e4 commit 0dbbed7

6 files changed

Lines changed: 50 additions & 3 deletions

File tree

‎vlib/v/gen/c/assign.v‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,8 +219,14 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
219219
}
220220
// Free the old value assigned to this string var (only if it's `str = [new value]`
221221
// or `x.str = [new value]` )
222-
mut af := g.is_autofree && !g.is_builtin_mod && node.op == .assign && node.left_types.len == 1
223-
&& node.left[0] in [ast.Ident, ast.SelectorExpr]
222+
mut af := g.is_autofree && !g.is_builtin_mod && !g.is_autofree_tmp && node.op == .assign
223+
&& node.left_types.len == 1 && node.left[0] in [ast.Ident, ast.SelectorExpr]
224+
if af && node.right.len == 1 && node.right[0] is ast.CallExpr {
225+
call_expr := node.right[0] as ast.CallExpr
226+
if call_expr.is_method && call_expr.left is ast.CallExpr {
227+
af = false
228+
}
229+
}
224230
mut sref_name := ''
225231
mut type_to_free := ''
226232
if af {

‎vlib/v/gen/c/cgen.v‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ mut:
102102
is_shared bool // for initialization of hidden mutex in `[rw]shared` literals
103103
is_vlines_enabled bool // is it safe to generate #line directives when -g is passed
104104
is_autofree bool // false, inside the bodies of fns marked with [manualfree], otherwise === g.pref.autofree
105+
is_autofree_tmp bool // when generating autofree temporary variables
105106
is_builtin_mod bool
106107
is_json_fn bool // inside json.encode()
107108
is_js_call bool // for handling a special type arg #1 `json.decode(User, ...)`

‎vlib/v/gen/c/fn.v‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2345,7 +2345,20 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) {
23452345
})
23462346
s = 'string ${t} = '
23472347
}
2348-
s += g.expr_string(arg.expr)
2348+
g.is_autofree_tmp = true
2349+
pos_before := g.out.len
2350+
2351+
old_is_autofree := g.is_autofree
2352+
if arg.expr is ast.CallExpr && arg.expr.is_method && arg.expr.left is ast.CallExpr {
2353+
g.is_autofree = false
2354+
}
2355+
2356+
g.expr(arg.expr)
2357+
expr_code := g.out.cut_to(pos_before).trim_space()
2358+
2359+
g.is_autofree = old_is_autofree
2360+
g.is_autofree_tmp = false
2361+
s += expr_code
23492362
s += ';// new af2 pre'
23502363
g.strs_to_free0 << s
23512364
// This tmp arg var will be freed with the rest of the vars at the end of the scope.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
void main__Test_set_tags(main__Test* t, string tags) {
2+
string _arg_expr_split_0_169 = builtin__string_trim_space(builtin__string_replace(builtin__string_to_lower(tags), _S(","), _S(" ")));// new af2 pre/* inserted before */
3+
t->tags = builtin__string_split(/*af receiver arg*/_arg_expr_split_0_169, _S(" "));
4+
builtin__string_free(&_arg_expr_split_0_169); // autofreed var main false
5+
}
6+
VV_LOC void main__main(void) {
7+
main__Test test = ((main__Test){.tags = builtin____new_array(0, 0, sizeof(string)),});
8+
main__Test_set_tags(&test, _S("Hello, World"));
9+
string _t1 = Array_string_str(test.tags); builtin__println(_t1); builtin__string_free(&_t1);
10+
;
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
['hello', '', 'world']
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// vtest vflags: -autofree
2+
pub struct Test {
3+
mut:
4+
tags []string
5+
}
6+
7+
pub fn (mut t Test) set_tags(tags string) {
8+
t.tags = tags.to_lower().replace(',', ' ').trim_space().split(' ')
9+
}
10+
11+
fn main() {
12+
mut test := Test{}
13+
test.set_tags('Hello, World')
14+
println(test.tags)
15+
}

0 commit comments

Comments
 (0)