From cc4af235f35aef67a692d0286ec090740e492602 Mon Sep 17 00:00:00 2001 From: 05st <60903484+05st@users.noreply.github.com> Date: Sat, 2 Oct 2021 06:30:04 -0500 Subject: [PATCH] cgen: fix if-expression code generation if it evaluates to propagating optional / or block (#12032) --- vlib/v/gen/c/cgen.v | 2 ++ vlib/v/gen/c/fn.v | 27 ++++++++++++++------------- vlib/v/tests/if_expression_test.v | 21 +++++++++++++++++++++ 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 387de05c35..2a500dde64 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4880,6 +4880,8 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool { if left_sym.kind in [.array, .array_fixed, .map] { return true } + } else if stmt.expr.or_block.kind != .absent { + return true } } } diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 9ff2b3d362..0f3e968009 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -560,7 +560,7 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { && g.pref.gc_mode in [.boehm_full, .boehm_incr, .boehm_full_opt, .boehm_incr_opt] gen_or := node.or_block.kind != .absent // && !g.is_autofree is_gen_or_and_assign_rhs := gen_or && !g.discard_or_result - cur_line := if is_gen_or_and_assign_rhs || gen_keep_alive { // && !g.is_autofree { + mut cur_line := if is_gen_or_and_assign_rhs || gen_keep_alive { // && !g.is_autofree { // `x := foo() or { ...}` // cut everything that has been generated to prepend optional variable creation line := g.go_before_stmt(0) @@ -577,6 +577,9 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { ret_typ = ret_typ.set_flag(.optional) } styp := g.typ(ret_typ) + if gen_or && !is_gen_or_and_assign_rhs { + cur_line = g.go_before_stmt(0) + } g.write('$styp $tmp_opt = ') } if node.is_method && !node.is_field { @@ -594,19 +597,17 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { // if !g.is_autofree { g.or_block(tmp_opt, node.or_block, node.return_type) //} - if is_gen_or_and_assign_rhs { - unwrapped_typ := node.return_type.clear_flag(.optional) - unwrapped_styp := g.typ(unwrapped_typ) - if unwrapped_typ == ast.void_type { - g.write('\n $cur_line') - } else if g.table.get_type_symbol(node.return_type).kind == .multi_return { - g.write('\n $cur_line $tmp_opt /*U*/') + unwrapped_typ := node.return_type.clear_flag(.optional) + unwrapped_styp := g.typ(unwrapped_typ) + if unwrapped_typ == ast.void_type { + g.write('\n $cur_line') + } else if g.table.get_type_symbol(node.return_type).kind == .multi_return { + g.write('\n $cur_line $tmp_opt /*U*/') + } else { + if !g.inside_const { + g.write('\n $cur_line (*($unwrapped_styp*)${tmp_opt}.data)') } else { - if !g.inside_const { - g.write('\n $cur_line (*($unwrapped_styp*)${tmp_opt}.data)') - } else { - g.write('\n $cur_line $tmp_opt') - } + g.write('\n $cur_line $tmp_opt') } } } else if gen_keep_alive { diff --git a/vlib/v/tests/if_expression_test.v b/vlib/v/tests/if_expression_test.v index 3955a4e6a4..544f6669e3 100644 --- a/vlib/v/tests/if_expression_test.v +++ b/vlib/v/tests/if_expression_test.v @@ -213,3 +213,24 @@ fn test_if_expr_with_complex_array_methods() { println(ret) assert ret == ['a', 'b', 'c'] } + +fn return_optional() ?int { + return 1 +} + +fn test_if_expr_with_optional() ? { + m := map[string]int{} + v := if a := m['a'] { + println('$a') + return_optional() ? + } else { + 2 + } + assert v == 2 +} + +fn test_if_expr_with_or_block() { + arr := ['a'] + a := if arr.len == 0 || arr[0] == '-' { 123 } else { return_optional() or { -1 } } + assert a == 1 +}