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() {
|
&& 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',
|
||||||
|
@ -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('*')
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
@ -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])
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user