1
0
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:
Felipe Pena 2023-05-24 21:52:45 -03:00 committed by GitHub
parent f1c647cbbe
commit 64a4a3316a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 6 deletions

View File

@ -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() { && node.left[i] in [ast.Ident, ast.SelectorExpr] && !node.left[i].is_blank_ident() {
c.expected_type = c.expr(node.left[i]) 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] { 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') 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 { if i == 0 {
right_type0 = right_type right_type0 = right_type
node.right_types = [ node.right_types = [
c.check_expr_opt_call(right, right_type0), c.check_expr_opt_call(right, right_type0),
] ]
} }
right_type_sym := c.table.sym(right_type)
if right_type_sym.kind == .multi_return { if right_type_sym.kind == .multi_return {
if node.right.len > 1 { if node.right.len > 1 {
c.error('cannot use multi-value ${right_type_sym.name} in single-value context', c.error('cannot use multi-value ${right_type_sym.name} in single-value context',

View File

@ -351,7 +351,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
right_sym := g.table.sym(unwrapped_val_type) right_sym := g.table.sym(unwrapped_val_type)
unaliased_right_sym := g.table.final_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 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.CastExpr && (val as ast.CastExpr).expr !is ast.ArrayInit)
|| (val is ast.UnsafeExpr && (val as ast.UnsafeExpr).expr is ast.Ident)) || (val is ast.UnsafeExpr && (val as ast.UnsafeExpr).expr is ast.Ident))
&& !g.pref.translated && !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) && (val as ast.CallExpr).or_block.kind == .propagate_option)
&& ((right_sym.info is ast.ArrayFixed && ((right_sym.info is ast.ArrayFixed
&& (right_sym.info as ast.ArrayFixed).is_fn_ret) && (right_sym.info as ast.ArrayFixed).is_fn_ret)
|| (val is ast.DumpExpr && right_sym.info is ast.ArrayFixed)
|| (val is ast.CallExpr || (val is ast.CallExpr
&& g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed)) && g.table.sym(g.unwrap_generic((val as ast.CallExpr).return_type)).kind == .array_fixed))
typ_str := g.typ(val_type).trim('*') typ_str := g.typ(val_type).trim('*')

View File

@ -2441,6 +2441,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
} }
// no cast // no cast
g.expr(expr) 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) { fn write_octal_escape(mut b strings.Builder, c u8) {

View File

@ -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)) 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 ptr_asterisk := if is_ptr { '*'.repeat(typ.nr_muls()) } else { '' }
mut str_dumparg_type := '' mut str_dumparg_type := ''
mut str_dumparg_ret_type := ''
if dump_sym.kind == .none_ { if dump_sym.kind == .none_ {
str_dumparg_type = 'IError' + ptr_asterisk str_dumparg_type = 'IError' + ptr_asterisk
} else { } else {
@ -103,11 +104,17 @@ fn (mut g Gen) dump_expr_definitions() {
str_tdef := g.out.after(tdef_pos) str_tdef := g.out.after(tdef_pos)
g.go_back(str_tdef.len) g.go_back(str_tdef.len)
dump_typedefs['typedef ${str_tdef};'] = true 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}' + dump_fn_name := '_v_dump_expr_${name}' +
(if is_ptr { '_ptr'.repeat(typ.nr_muls()) } else { '' }) (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);') 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_type} ${dump_fn_name}(string fpath, int line, string sexpr, ${str_dumparg_type} dump_arg)', mut 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) dump_fns)
{ {
continue 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_string(&sb, value);')
dump_fns.writeln("\tstrings__Builder_write_rune(&sb, '\\n');") dump_fns.writeln("\tstrings__Builder_write_rune(&sb, '\\n');")
surrounder.builder_write_afters(mut dump_fns) 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('}') dump_fns.writeln('}')
} }
for tdef, _ in dump_typedefs { for tdef, _ in dump_typedefs {

View File

@ -88,3 +88,28 @@ fn test_inline() {
mut a := [1, 2, 3, 4]! mut a := [1, 2, 3, 4]!
assert four(a)[1] == 2 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])
}