From 5db3330069617c4be85df44ffce5ea0538812f53 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 26 Feb 2026 11:42:16 +0300 Subject: [PATCH] cgen: fix -autofree C compiler error (fixes #23527) --- vlib/v/gen/c/cgen.v | 2 +- vlib/v/gen/c/fn.v | 18 ++++++++++-- ...tofree_compare_strings_if_expr.c.must_have | 4 +++ .../autofree_compare_strings_if_expr.vv | 29 +++++++++++++++++++ 4 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.c.must_have create mode 100644 vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.vv diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index fcc36e78d..f7fdab2e9 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4021,7 +4021,7 @@ fn (mut g Gen) expr(node_ ast.Expr) { } g.call_expr(node) if g.is_autofree && !g.is_builtin_mod && !g.is_js_call && g.strs_to_free0.len == 0 - && !g.is_autofree_tmp && !g.inside_lambda { + && !g.is_autofree_tmp && !g.inside_lambda && g.inside_ternary == 0 { // if len != 0, that means we are handling call expr inside call expr (arg) // and it'll get messed up here, since it's handled recursively in autofree_call_pregen() // so just skip it diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index b68f36405..9cc8e34d4 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2414,7 +2414,6 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) { if arg.expr is ast.CallExpr && arg.expr.is_method && arg.expr.left is ast.CallExpr { g.is_autofree = false } - tmp_arg_init := g.autofree_tmp_arg_init_stmt(s, arg.expr) g.is_autofree = old_is_autofree g.is_autofree_tmp = false @@ -2637,7 +2636,7 @@ fn (mut g Gen) call_args(node ast.CallExpr) { } } use_tmp_var_autofree := g.is_autofree && arg.typ == ast.string_type && arg.is_tmp_autofree - && !g.inside_const && !g.is_builtin_mod + && !g.inside_const && !g.is_builtin_mod && g.inside_ternary == 0 // g.write('/* af=${arg.is_tmp_autofree} */') // some c fn definitions dont have args (cfns.v) or are not updated in checker // when these are fixed we wont need this check @@ -2653,7 +2652,20 @@ fn (mut g Gen) call_args(node ast.CallExpr) { name := '_arg_expr_${fn_name}_${i + 1}_${node.pos.pos}' scope := g.file.scope.innermost(node.pos.pos) if !g.is_autofree_tmp || scope.known_var(name) { - g.write('/*autofree arg*/' + name) + tmp_arg := ast.CallArg{ + typ: arg.typ + is_mut: arg.is_mut + expr: ast.Ident{ + name: name + kind: .variable + info: ast.IdentVar{ + typ: arg.typ + is_mut: arg.is_mut + } + } + } + g.write('/*autofree arg*/') + g.ref_or_deref_arg(tmp_arg, expected_types[i], node.language, is_smartcast) wrote_tmp_arg = true } } diff --git a/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.c.must_have b/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.c.must_have new file mode 100644 index 000000000..f4338018a --- /dev/null +++ b/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.c.must_have @@ -0,0 +1,4 @@ +builtin__compare_strings(/*autofree arg*/(voidptr)&_arg_expr_compare_strings_1_ +builtin__compare_strings(ADDR(string, builtin__string_to_lower(a)), ADDR(string, builtin__string_to_lower(b))) +string _arg_expr_main_right_pad_end_1_ +right_pad_end(/*autofree arg*/_arg_expr_main_right_pad_end_1_ diff --git a/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.vv b/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.vv new file mode 100644 index 000000000..e3780939f --- /dev/null +++ b/vlib/v/gen/c/testdata/autofree_compare_strings_if_expr.vv @@ -0,0 +1,29 @@ +// vtest vflags: -autofree +import os + +fn string_compare(a string, b string, ignore_case bool) int { + return match ignore_case { + true { compare_strings(a.to_lower(), b.to_lower()) } + else { compare_strings(a, b) } + } +} + +fn right_pad_end(s string, width int) string { + pad := width - s.len + if pad > 0 { + return s + ' '.repeat(pad) + } + return s +} + +fn main() { + ext_cmp := compare_strings(os.file_ext('foo.v'), os.file_ext('bar.md')) + println(ext_cmp) + println(string_compare('Ab', 'aB', true)) + show_header := true + title := 'name' + mut buffer := '>' + buffer += right_pad_end(if show_header { title } else { '' }, 6) + buffer += '<' + println(buffer) +} -- 2.39.5