mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix opt ptr argument passing with and without heap usage (#18423)
This commit is contained in:
parent
24c09881f7
commit
ada702ec66
@ -7,12 +7,15 @@ import v.ast
|
||||
import v.util
|
||||
import v.token
|
||||
|
||||
fn (mut g Gen) expr_with_opt_or_block(expr ast.Expr, expr_typ ast.Type, var_expr ast.Expr, ret_typ ast.Type) {
|
||||
fn (mut g Gen) expr_with_opt_or_block(expr ast.Expr, expr_typ ast.Type, var_expr ast.Expr, ret_typ ast.Type, in_heap bool) {
|
||||
gen_or := expr is ast.Ident && (expr as ast.Ident).or_expr.kind != .absent
|
||||
if gen_or {
|
||||
old_inside_opt_or_res := g.inside_opt_or_res
|
||||
g.inside_opt_or_res = true
|
||||
g.expr_with_cast(expr, expr_typ, ret_typ)
|
||||
if in_heap {
|
||||
g.write('))')
|
||||
}
|
||||
g.writeln(';')
|
||||
expr_var := if expr is ast.Ident && (expr as ast.Ident).is_auto_heap() {
|
||||
'(*${expr.name})'
|
||||
@ -575,7 +578,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
g.write('${styp} ')
|
||||
}
|
||||
}
|
||||
if is_auto_heap {
|
||||
if is_auto_heap && !(val_type.is_ptr() && val_type.has_flag(.option)) {
|
||||
g.write('*')
|
||||
}
|
||||
}
|
||||
@ -665,15 +668,18 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
g.write('{0}')
|
||||
}
|
||||
} else {
|
||||
is_option_unwrapped := (val is ast.Ident
|
||||
&& (val as ast.Ident).or_expr.kind != .absent)
|
||||
is_option_auto_heap := is_auto_heap && is_option_unwrapped
|
||||
if is_auto_heap {
|
||||
g.write('HEAP(${styp}, (')
|
||||
}
|
||||
if val.is_auto_deref_var() {
|
||||
if val.is_auto_deref_var() && !is_option_unwrapped {
|
||||
g.write('*')
|
||||
}
|
||||
if (var_type.has_flag(.option) && val !in [ast.Ident, ast.SelectorExpr])
|
||||
|| gen_or {
|
||||
g.expr_with_opt_or_block(val, val_type, left, var_type)
|
||||
g.expr_with_opt_or_block(val, val_type, left, var_type, is_option_auto_heap)
|
||||
} else if val is ast.ArrayInit {
|
||||
g.array_init(val, c_name(ident.name))
|
||||
} else if val_type.has_flag(.shared_f) {
|
||||
@ -681,7 +687,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
} else {
|
||||
g.expr(val)
|
||||
}
|
||||
if is_auto_heap {
|
||||
if is_auto_heap && !is_option_auto_heap {
|
||||
g.write('))')
|
||||
}
|
||||
}
|
||||
@ -695,7 +701,7 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
g.is_option_auto_heap = old_is_auto_heap
|
||||
}
|
||||
if var_type.has_flag(.option) || gen_or {
|
||||
g.expr_with_opt_or_block(val, val_type, left, var_type)
|
||||
g.expr_with_opt_or_block(val, val_type, left, var_type, false)
|
||||
} else if node.has_cross_var {
|
||||
g.gen_cross_tmp_variable(node.left, val)
|
||||
} else {
|
||||
|
@ -1898,6 +1898,9 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
|
||||
} else {
|
||||
g.write('_option_ok(&(${styp}[]) { ')
|
||||
}
|
||||
if !expr_typ.is_ptr() && ret_typ.is_ptr() {
|
||||
g.write('&/*ref*/')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
g.write('_result_ok(&(${styp}[]) { ')
|
||||
|
@ -2193,7 +2193,12 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type ast.Type, lang as
|
||||
if arg_typ_sym.kind != .function && deref_sym.kind !in [.sum_type, .interface_]
|
||||
&& lang != .c {
|
||||
if arg.expr.is_lvalue() {
|
||||
g.write('(voidptr)&/*qq*/')
|
||||
if expected_type.has_flag(.option) {
|
||||
g.expr_with_opt(arg.expr, arg_typ, expected_type)
|
||||
return
|
||||
} else {
|
||||
g.write('(voidptr)&/*qq*/')
|
||||
}
|
||||
} else {
|
||||
mut atype := expected_deref_type
|
||||
if atype.has_flag(.generic) {
|
||||
|
25
vlib/v/tests/option_ptr_arg_heap_test.v
Normal file
25
vlib/v/tests/option_ptr_arg_heap_test.v
Normal file
@ -0,0 +1,25 @@
|
||||
module main
|
||||
|
||||
[heap]
|
||||
struct Node[T] {
|
||||
mut:
|
||||
value T
|
||||
next ?&Node[T]
|
||||
}
|
||||
|
||||
fn print_t1(node ?&Node[int]) {
|
||||
println(node)
|
||||
}
|
||||
|
||||
fn print_t2(mut node ?&Node[int]) {
|
||||
n := node or { return }
|
||||
println(n)
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
mut n := Node[int]{
|
||||
value: 5
|
||||
}
|
||||
print_t1(n)
|
||||
print_t2(mut n.next)
|
||||
}
|
24
vlib/v/tests/option_ptr_arg_test.v
Normal file
24
vlib/v/tests/option_ptr_arg_test.v
Normal file
@ -0,0 +1,24 @@
|
||||
module main
|
||||
|
||||
struct Node[T] {
|
||||
mut:
|
||||
value T
|
||||
next ?&Node[T]
|
||||
}
|
||||
|
||||
fn print_t1(node ?&Node[int]) {
|
||||
println(node)
|
||||
}
|
||||
|
||||
fn print_t2(mut node ?&Node[int]) {
|
||||
n := node or { return }
|
||||
println(n)
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
mut n := Node[int]{
|
||||
value: 5
|
||||
}
|
||||
print_t1(n)
|
||||
print_t2(mut n.next)
|
||||
}
|
Loading…
Reference in New Issue
Block a user