mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker, cgen: fix fixed array return on assigning, arg pass and dumping (#18216)
This commit is contained in:
parent
f1c647cbbe
commit
64a4a3316a
@ -26,17 +26,24 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
&& node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() {
|
||||
c.expected_type = c.expr(node.left[i])
|
||||
}
|
||||
right_type := c.expr(right)
|
||||
mut right_type := c.expr(right)
|
||||
if right in [ast.CallExpr, ast.IfExpr, ast.LockExpr, ast.MatchExpr, ast.DumpExpr] {
|
||||
c.fail_if_unreadable(right, right_type, 'right-hand side of assignment')
|
||||
}
|
||||
right_type_sym := c.table.sym(right_type)
|
||||
// fixed array returns an struct, but when assigning it must be the array type
|
||||
if right_type_sym.kind == .array_fixed
|
||||
&& (right_type_sym.info as ast.ArrayFixed).is_fn_ret {
|
||||
info := right_type_sym.info as ast.ArrayFixed
|
||||
right_type = c.table.find_or_register_array_fixed(info.elem_type, info.size,
|
||||
info.size_expr, false)
|
||||
}
|
||||
if i == 0 {
|
||||
right_type0 = right_type
|
||||
node.right_types = [
|
||||
c.check_expr_opt_call(right, right_type0),
|
||||
]
|
||||
}
|
||||
right_type_sym := c.table.sym(right_type)
|
||||
if right_type_sym.kind == .multi_return {
|
||||
if node.right.len > 1 {
|
||||
c.error('cannot use multi-value ${right_type_sym.name} in single-value context',
|
||||
|
@ -351,7 +351,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
right_sym := g.table.sym(unwrapped_val_type)
|
||||
unaliased_right_sym := g.table.final_sym(unwrapped_val_type)
|
||||
is_fixed_array_var := unaliased_right_sym.kind == .array_fixed && val !is ast.ArrayInit
|
||||
&& (val in [ast.Ident, ast.IndexExpr, ast.CallExpr, ast.SelectorExpr]
|
||||
&& (val in [ast.Ident, ast.IndexExpr, ast.CallExpr, ast.SelectorExpr, ast.DumpExpr]
|
||||
|| (val is ast.CastExpr && (val as ast.CastExpr).expr !is ast.ArrayInit)
|
||||
|| (val is ast.UnsafeExpr && (val as ast.UnsafeExpr).expr is ast.Ident))
|
||||
&& !g.pref.translated
|
||||
@ -631,6 +631,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
&& (val as ast.CallExpr).or_block.kind == .propagate_option)
|
||||
&& ((right_sym.info is ast.ArrayFixed
|
||||
&& (right_sym.info as ast.ArrayFixed).is_fn_ret)
|
||||
|| (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed)
|
||||
|| (val is ast.CallExpr
|
||||
&& g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed))
|
||||
typ_str := g.typ(val_type).trim('*')
|
||||
|
@ -2441,6 +2441,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
|
||||
}
|
||||
// no cast
|
||||
g.expr(expr)
|
||||
if expr is ast.CallExpr && exp_sym.kind == .array_fixed {
|
||||
g.write('.ret_arr')
|
||||
}
|
||||
}
|
||||
|
||||
fn write_octal_escape(mut b strings.Builder, c u8) {
|
||||
|
@ -86,6 +86,7 @@ fn (mut g Gen) dump_expr_definitions() {
|
||||
to_string_fn_name := g.get_str_fn(typ.clear_flags(.shared_f, .result))
|
||||
mut ptr_asterisk := if is_ptr { '*'.repeat(typ.nr_muls()) } else { '' }
|
||||
mut str_dumparg_type := ''
|
||||
mut str_dumparg_ret_type := ''
|
||||
if dump_sym.kind == .none_ {
|
||||
str_dumparg_type = 'IError' + ptr_asterisk
|
||||
} else {
|
||||
@ -103,11 +104,17 @@ fn (mut g Gen) dump_expr_definitions() {
|
||||
str_tdef := g.out.after(tdef_pos)
|
||||
g.go_back(str_tdef.len)
|
||||
dump_typedefs['typedef ${str_tdef};'] = true
|
||||
str_dumparg_ret_type = str_dumparg_type
|
||||
} else if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
|
||||
// fixed array returned from function
|
||||
str_dumparg_ret_type = '_v_' + str_dumparg_type
|
||||
} else {
|
||||
str_dumparg_ret_type = str_dumparg_type
|
||||
}
|
||||
dump_fn_name := '_v_dump_expr_${name}' +
|
||||
(if is_ptr { '_ptr'.repeat(typ.nr_muls()) } else { '' })
|
||||
dump_fn_defs.writeln('${str_dumparg_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg);')
|
||||
if g.writeln_fn_header('${str_dumparg_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg)', mut
|
||||
dump_fn_defs.writeln('${str_dumparg_ret_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg);')
|
||||
if g.writeln_fn_header('${str_dumparg_ret_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg)', mut
|
||||
dump_fns)
|
||||
{
|
||||
continue
|
||||
@ -157,7 +164,14 @@ fn (mut g Gen) dump_expr_definitions() {
|
||||
dump_fns.writeln('\tstrings__Builder_write_string(&sb, value);')
|
||||
dump_fns.writeln("\tstrings__Builder_write_rune(&sb, '\\n');")
|
||||
surrounder.builder_write_afters(mut dump_fns)
|
||||
dump_fns.writeln('\treturn dump_arg;')
|
||||
if !typ.has_flag(.option) && dump_sym.kind == .array_fixed {
|
||||
tmp_var := g.new_tmp_var()
|
||||
dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = {0};')
|
||||
dump_fns.writeln('\tmemcpy(${tmp_var}.ret_arr, dump_arg, sizeof(${str_dumparg_type}));')
|
||||
dump_fns.writeln('\treturn ${tmp_var};')
|
||||
} else {
|
||||
dump_fns.writeln('\treturn dump_arg;')
|
||||
}
|
||||
dump_fns.writeln('}')
|
||||
}
|
||||
for tdef, _ in dump_typedefs {
|
||||
|
@ -88,3 +88,28 @@ fn test_inline() {
|
||||
mut a := [1, 2, 3, 4]!
|
||||
assert four(a)[1] == 2
|
||||
}
|
||||
|
||||
fn f() [4]int {
|
||||
return [1, 2, 3, 4]!
|
||||
}
|
||||
|
||||
fn test_simple_ret() {
|
||||
zzz := f()
|
||||
dump(zzz)
|
||||
dump(zzz[0])
|
||||
}
|
||||
|
||||
fn g(a [4]int) {
|
||||
}
|
||||
|
||||
fn test_arg_fixed() {
|
||||
zzz := f()
|
||||
g(zzz)
|
||||
g(f())
|
||||
}
|
||||
|
||||
fn test_dump_ret() {
|
||||
zzz := f()
|
||||
a := dump(zzz)
|
||||
b := dump(zzz[0])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user