Skip to content

Commit

Permalink
cgen: fix opt ptr argument passing with and without heap usage (#18423)
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp committed Jun 13, 2023
1 parent 24c0988 commit ada702e
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 7 deletions.
18 changes: 12 additions & 6 deletions vlib/v/gen/c/assign.v
Original file line number Diff line number Diff line change
Expand Up @@ -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})'
Expand Down Expand Up @@ -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('*')
}
}
Expand Down Expand Up @@ -665,23 +668,26 @@ 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) {
g.expr_with_cast(val, val_type, var_type)
} else {
g.expr(val)
}
if is_auto_heap {
if is_auto_heap && !is_option_auto_heap {
g.write('))')
}
}
Expand All @@ -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 {
Expand Down
3 changes: 3 additions & 0 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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}[]) { ')
Expand Down
7 changes: 6 additions & 1 deletion vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
25 changes: 25 additions & 0 deletions vlib/v/tests/option_ptr_arg_heap_test.v
Original file line number Diff line number Diff line change
@@ -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 changes: 24 additions & 0 deletions vlib/v/tests/option_ptr_arg_test.v
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit ada702e

Please sign in to comment.