From db49874ab3ce63c7d1e1d27018d6a51694526481 Mon Sep 17 00:00:00 2001 From: yuyi Date: Mon, 9 Dec 2024 22:25:37 +0800 Subject: [PATCH] cgen: fix printing fn call of returning c struct value (fix #23104) (#23106) --- vlib/v/gen/c/str.v | 24 ++++++++++++++++++++-- vlib/v/tests/c_structs/csize.h | 4 ++++ vlib/v/tests/c_structs/return_csize_test.v | 23 +++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 vlib/v/tests/c_structs/csize.h create mode 100644 vlib/v/tests/c_structs/return_csize_test.v diff --git a/vlib/v/gen/c/str.v b/vlib/v/gen/c/str.v index 6f275e0d3..cc0272847 100644 --- a/vlib/v/gen/c/str.v +++ b/vlib/v/gen/c/str.v @@ -118,7 +118,8 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { is_dump_expr := expr is ast.DumpExpr is_var_mut := expr.is_auto_deref_var() str_fn_name := g.get_str_fn(exp_typ) - temp_var_needed := expr is ast.CallExpr && expr.return_type.is_ptr() + temp_var_needed := expr is ast.CallExpr + && (expr.return_type.is_ptr() || g.table.sym(expr.return_type).is_c_struct()) mut tmp_var := '' if temp_var_needed { tmp_var = g.new_tmp_var() @@ -206,6 +207,21 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { str_fn_name := g.get_str_fn(typ) g.write('${str_fn_name}(') if sym.kind != .function { + unwrap_option := expr is ast.Ident && expr.or_expr.kind == .propagate_option + exp_typ := if unwrap_option { typ.clear_flag(.option) } else { typ } + temp_var_needed := expr is ast.CallExpr + && (expr.return_type.is_ptr() || g.table.sym(expr.return_type).is_c_struct()) + mut tmp_var := '' + if temp_var_needed { + tmp_var = g.new_tmp_var() + ret_typ := g.styp(exp_typ) + line := g.go_before_last_stmt().trim_space() + g.empty_line = true + g.write('${ret_typ} ${tmp_var} = ') + g.expr(expr) + g.writeln(';') + g.write(line) + } if str_method_expects_ptr && !is_ptr && !typ.has_flag(.option) { g.write('&') } else if (!str_method_expects_ptr && is_ptr && !is_shared) || is_var_mut { @@ -215,7 +231,11 @@ fn (mut g Gen) gen_expr_to_string(expr ast.Expr, etype ast.Type) { g.write(c_struct_ptr(sym, typ, str_method_expects_ptr)) } } - g.expr_with_cast(expr, typ, typ) + if temp_var_needed { + g.write(tmp_var) + } else { + g.expr_with_cast(expr, typ, typ) + } } else if typ.has_flag(.option) { // only Option fn receive argument g.expr_with_cast(expr, typ, typ) diff --git a/vlib/v/tests/c_structs/csize.h b/vlib/v/tests/c_structs/csize.h new file mode 100644 index 000000000..01f605cf7 --- /dev/null +++ b/vlib/v/tests/c_structs/csize.h @@ -0,0 +1,4 @@ +struct Size { + int width; + int height; +}; diff --git a/vlib/v/tests/c_structs/return_csize_test.v b/vlib/v/tests/c_structs/return_csize_test.v new file mode 100644 index 000000000..054ea282d --- /dev/null +++ b/vlib/v/tests/c_structs/return_csize_test.v @@ -0,0 +1,23 @@ +#include "@VMODROOT/csize.h" + +struct C.Size { + width int + height int +} + +type Size = C.Size + +fn get_size() C.Size { + return C.Size{11, 22} +} + +fn get_csize() Size { + return Size(C.Size{11, 22}) +} + +fn test_return_csize() { + println(get_size()) + assert true + println(get_csize()) + assert true +} -- 2.39.5