1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser, checker, cgen: fix swapping arrays (#18204)

This commit is contained in:
yuyi 2023-05-20 07:23:50 +08:00 committed by GitHub
parent 332235548e
commit 94217571cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 64 additions and 12 deletions

View File

@ -258,7 +258,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
if !is_decl && left is ast.Ident && !is_blank_ident && !left_type.is_real_pointer()
&& right_type.is_real_pointer() && !right_type.has_flag(.shared_f) {
left_sym := c.table.sym(left_type)
if left_sym.kind != .function {
if left_sym.kind !in [.function, .array] {
c.warn(
'cannot assign a reference to a value (this will be an error soon) left=${c.table.type_str(left_type)} ${left_type.is_ptr()} ' +
'right=${c.table.type_str(right_type)} ${right_type.is_real_pointer()} ptr=${right_type.is_ptr()}',

View File

@ -843,6 +843,7 @@ fn (mut g Gen) gen_assign_vars_autofree(node &ast.AssignStmt) {
fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
for i, left in node.left {
left_is_auto_deref_var := left.is_auto_deref_var()
match left {
ast.Ident {
left_typ := node.left_types[i]
@ -851,9 +852,20 @@ fn (mut g Gen) gen_cross_var_assign(node &ast.AssignStmt) {
if left_sym.kind == .function {
g.write_fn_ptr_decl(left_sym.info as ast.FnType, '_var_${left.pos.pos}')
g.writeln(' = ${anon_ctx}${c_name(left.name)};')
} else if left_is_auto_deref_var {
styp := g.typ(left_typ).trim('*')
if left_sym.kind == .array {
g.writeln('${styp} _var_${left.pos.pos} = array_clone(${anon_ctx}${c_name(left.name)});')
} else {
g.writeln('${styp} _var_${left.pos.pos} = *${anon_ctx}${c_name(left.name)};')
}
} else {
styp := g.typ(left_typ)
g.writeln('${styp} _var_${left.pos.pos} = ${anon_ctx}${c_name(left.name)};')
if left_sym.kind == .array {
g.writeln('${styp} _var_${left.pos.pos} = array_clone(&${anon_ctx}${c_name(left.name)});')
} else {
g.writeln('${styp} _var_${left.pos.pos} = ${anon_ctx}${c_name(left.name)};')
}
}
}
ast.IndexExpr {
@ -1009,18 +1021,36 @@ fn (mut g Gen) gen_cross_tmp_variable(left []ast.Expr, val ast.Expr) {
g.write(')')
}
ast.CallExpr {
mut fn_name := val.name.replace('.', '__')
if val.concrete_types.len > 0 {
fn_name = g.generic_fn_name(val.concrete_types, fn_name)
}
g.write('${fn_name}(')
for i, arg in val.args {
g.gen_cross_tmp_variable(left, arg.expr)
if i != val.args.len - 1 {
g.write(', ')
if val.is_method {
rec_cc_type := g.cc_type(val.receiver_type, false)
mut rec_typ_name := util.no_dots(rec_cc_type)
if g.table.sym(val.receiver_type).kind == .array {
rec_typ_name = 'array'
}
fn_name := util.no_dots('${rec_typ_name}_${val.name}')
g.write('${fn_name}(&')
g.gen_cross_tmp_variable(left, val.left)
for i, arg in val.args {
g.gen_cross_tmp_variable(left, arg.expr)
if i != val.args.len - 1 {
g.write(', ')
}
}
g.write(')')
} else {
mut fn_name := val.name.replace('.', '__')
if val.concrete_types.len > 0 {
fn_name = g.generic_fn_name(val.concrete_types, fn_name)
}
g.write('${fn_name}(')
for i, arg in val.args {
g.gen_cross_tmp_variable(left, arg.expr)
if i != val.args.len - 1 {
g.write(', ')
}
}
g.write(')')
}
g.write(')')
}
ast.PrefixExpr {
g.write(val.op.str())

View File

@ -157,6 +157,9 @@ fn (mut p Parser) check_cross_variables(exprs []ast.Expr, val ast.Expr) bool {
return p.check_cross_variables(exprs, val.expr)
}
ast.CallExpr {
if p.check_cross_variables(exprs, val.left) {
return true
}
for arg in val.args {
if p.check_cross_variables(exprs, arg.expr) {
return true

View File

@ -0,0 +1,19 @@
fn test_swap_array() {
mut array1 := []int{len: 10, init: 1}
println(array1)
swaper(mut array1)
println(array1)
assert array1 == [22, 2, 2, 2, 2, 2, 2, 2, 2, 2]
}
fn swaper(mut array1 []int) {
mut array2 := []int{len: 10, init: 2}
array1[0] = 11
array2[0] = 22
unsafe {
array1, array2 = array2, array1
}
}