Skip to content

Commit cc4af23

Browse files
authored
cgen: fix if-expression code generation if it evaluates to propagating optional / or block (#12032)
1 parent 552daea commit cc4af23

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

vlib/v/gen/c/cgen.v

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4880,6 +4880,8 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool {
48804880
if left_sym.kind in [.array, .array_fixed, .map] {
48814881
return true
48824882
}
4883+
} else if stmt.expr.or_block.kind != .absent {
4884+
return true
48834885
}
48844886
}
48854887
}

vlib/v/gen/c/fn.v

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
560560
&& g.pref.gc_mode in [.boehm_full, .boehm_incr, .boehm_full_opt, .boehm_incr_opt]
561561
gen_or := node.or_block.kind != .absent // && !g.is_autofree
562562
is_gen_or_and_assign_rhs := gen_or && !g.discard_or_result
563-
cur_line := if is_gen_or_and_assign_rhs || gen_keep_alive { // && !g.is_autofree {
563+
mut cur_line := if is_gen_or_and_assign_rhs || gen_keep_alive { // && !g.is_autofree {
564564
// `x := foo() or { ...}`
565565
// cut everything that has been generated to prepend optional variable creation
566566
line := g.go_before_stmt(0)
@@ -577,6 +577,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
577577
ret_typ = ret_typ.set_flag(.optional)
578578
}
579579
styp := g.typ(ret_typ)
580+
if gen_or && !is_gen_or_and_assign_rhs {
581+
cur_line = g.go_before_stmt(0)
582+
}
580583
g.write('$styp $tmp_opt = ')
581584
}
582585
if node.is_method && !node.is_field {
@@ -594,19 +597,17 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
594597
// if !g.is_autofree {
595598
g.or_block(tmp_opt, node.or_block, node.return_type)
596599
//}
597-
if is_gen_or_and_assign_rhs {
598-
unwrapped_typ := node.return_type.clear_flag(.optional)
599-
unwrapped_styp := g.typ(unwrapped_typ)
600-
if unwrapped_typ == ast.void_type {
601-
g.write('\n $cur_line')
602-
} else if g.table.get_type_symbol(node.return_type).kind == .multi_return {
603-
g.write('\n $cur_line $tmp_opt /*U*/')
600+
unwrapped_typ := node.return_type.clear_flag(.optional)
601+
unwrapped_styp := g.typ(unwrapped_typ)
602+
if unwrapped_typ == ast.void_type {
603+
g.write('\n $cur_line')
604+
} else if g.table.get_type_symbol(node.return_type).kind == .multi_return {
605+
g.write('\n $cur_line $tmp_opt /*U*/')
606+
} else {
607+
if !g.inside_const {
608+
g.write('\n $cur_line (*($unwrapped_styp*)${tmp_opt}.data)')
604609
} else {
605-
if !g.inside_const {
606-
g.write('\n $cur_line (*($unwrapped_styp*)${tmp_opt}.data)')
607-
} else {
608-
g.write('\n $cur_line $tmp_opt')
609-
}
610+
g.write('\n $cur_line $tmp_opt')
610611
}
611612
}
612613
} else if gen_keep_alive {

vlib/v/tests/if_expression_test.v

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,24 @@ fn test_if_expr_with_complex_array_methods() {
213213
println(ret)
214214
assert ret == ['a', 'b', 'c']
215215
}
216+
217+
fn return_optional() ?int {
218+
return 1
219+
}
220+
221+
fn test_if_expr_with_optional() ? {
222+
m := map[string]int{}
223+
v := if a := m['a'] {
224+
println('$a')
225+
return_optional() ?
226+
} else {
227+
2
228+
}
229+
assert v == 2
230+
}
231+
232+
fn test_if_expr_with_or_block() {
233+
arr := ['a']
234+
a := if arr.len == 0 || arr[0] == '-' { 123 } else { return_optional() or { -1 } }
235+
assert a == 1
236+
}

0 commit comments

Comments
 (0)