From 107167a93afb952f9fdaa996c506be8c3ff52369 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Wed, 6 Nov 2024 22:37:50 -0300 Subject: [PATCH] autofree: fix argument freeing for json.encode and json.encode_pretty calls (#22781) --- vlib/v/checker/fn.v | 3 +++ vlib/v/gen/c/fn.v | 12 +++++++++++- .../c/testdata/autofree_json_encode.c.must_have | 5 +++++ vlib/v/gen/c/testdata/autofree_json_encode.vv | 16 ++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 vlib/v/gen/c/testdata/autofree_json_encode.c.must_have create mode 100644 vlib/v/gen/c/testdata/autofree_json_encode.vv diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 605dac77d80bbe..a12639b4d9d34b 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -705,6 +705,9 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type { // Only expressions like `str + 'b'` need to be freed. continue } + if arg.expr is ast.CallExpr && arg.expr.name in ['json.encode', 'json.encode_pretty'] { + continue + } node.args[i].is_tmp_autofree = true } // TODO: copy pasta from above diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 55efc5a0aa1a10..ff301a97501af8 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2073,7 +2073,11 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { g.write('cJSON* ${json_obj} = ${encode_name}(') g.call_args(node) g.writeln(');') - tmp2 = g.new_tmp_var() + tmp2 = if g.is_autofree { + '_arg_expr_${node.name.replace('.', '_')}_${node.pos.pos}' + } else { + g.new_tmp_var() + } if is_json_encode { g.writeln('string ${tmp2} = json__json_print(${json_obj});') } else { @@ -2421,6 +2425,12 @@ fn (mut g Gen) autofree_call_pregen(node ast.CallExpr) { args << node.args for i, arg in args { if !arg.is_tmp_autofree { + if arg.expr is ast.CallExpr && arg.expr.name in ['json.encode', 'json.encode_pretty'] { + t := '_arg_expr_${arg.expr.name.replace('.', '_')}_${arg.expr.pos.pos}' + defer { + g.writeln(';\n\tstring_free(&${t});') + } + } continue } if arg.expr is ast.CallExpr { diff --git a/vlib/v/gen/c/testdata/autofree_json_encode.c.must_have b/vlib/v/gen/c/testdata/autofree_json_encode.c.must_have new file mode 100644 index 00000000000000..ba8ddda3cce027 --- /dev/null +++ b/vlib/v/gen/c/testdata/autofree_json_encode.c.must_have @@ -0,0 +1,5 @@ +string _arg_expr_json_encode_pretty +string_free(&_arg_expr_json_encode_pretty_ +string _arg_expr_json_encode_ +string d = (_arg_expr_json_encode_ +string_free(&d); // autofreed var main false \ No newline at end of file diff --git a/vlib/v/gen/c/testdata/autofree_json_encode.vv b/vlib/v/gen/c/testdata/autofree_json_encode.vv new file mode 100644 index 00000000000000..9f61c35ce944dc --- /dev/null +++ b/vlib/v/gen/c/testdata/autofree_json_encode.vv @@ -0,0 +1,16 @@ +// vtest vflags: -autofree +import json + +struct Foo { + foo int +} + +fn main() { + mut a := { + 'foo': 123 + } + println(json.encode_pretty(a)) + d := json.encode(a) + dump(d) + println(json.decode(Foo, d)!) +}