From 50fd4fd6e039aa7bc2bfc6c84e72ec4c4217e314 Mon Sep 17 00:00:00 2001 From: JMD <56417208+StunxFS@users.noreply.github.com> Date: Fri, 31 Oct 2025 03:54:27 -0400 Subject: [PATCH] cgen: fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621) --- vlib/v/gen/c/if.v | 25 ++++++++++++++--- ...f_expr_with_condition_using_tmp_var_test.v | 27 +++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/conditions/ifs/if_expr_with_condition_using_tmp_var_test.v diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index a7310f89c..0ae7d7164 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -197,7 +197,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { mut cur_line := '' mut raw_state := false tmp_if_option_type := g.last_if_option_type + mut exit_label := '' if needs_tmp_var { + exit_label = g.new_tmp_var() mut styp := g.styp(node.typ) if g.inside_if_option || node.typ.has_flag(.option) { raw_state = g.inside_if_option @@ -235,9 +237,11 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { g.write('${styp} ') } g.writeln('${tmp}; /* if prepend */') + g.set_current_pos_as_last_stmt_pos() } if g.infix_left_var_name.len > 0 { g.writeln('if (${g.infix_left_var_name}) {') + g.set_current_pos_as_last_stmt_pos() g.indent++ } } else if node.is_expr || g.inside_ternary != 0 { @@ -303,11 +307,17 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { } mut branch_cond_var_names := []string{} for i, branch in node.branches { + is_else := i == node.branches.len - 1 && node.has_else if i > 0 { - g.write('} else ') + if needs_tmp_var { + g.writeln('};') + g.set_current_pos_as_last_stmt_pos() + } else { + g.write('} else ') + } } // if last branch is `else {` - if i == node.branches.len - 1 && node.has_else { + if is_else { g.writeln('{') // define `err` for the last branch after a `if val := opt {...}' guard if is_guard && guard_idx == i - 1 { @@ -475,6 +485,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { } g.stmts_with_tmp_var(branch.stmts, tmp) g.expected_cast_type = prev_expected_cast_type + if !is_else && (branch.stmts.len > 0 + && branch.stmts[branch.stmts.len - 1] !in [ast.Return, ast.BranchStmt]) { + g.writeln('\tgoto ${exit_label};') + } } else { // restore if_expr stmt header pos stmt_pos := g.nth_stmt_pos(0) @@ -484,15 +498,18 @@ fn (mut g Gen) if_expr(node ast.IfExpr) { } if node.branches.len > 0 { g.writeln('}') - g.set_current_pos_as_last_stmt_pos() + if !needs_tmp_var { + g.set_current_pos_as_last_stmt_pos() + } } if needs_tmp_var { if g.infix_left_var_name.len > 0 { g.indent-- g.writeln('}') - g.set_current_pos_as_last_stmt_pos() } g.empty_line = false + g.writeln('\t${exit_label}: {};') + g.set_current_pos_as_last_stmt_pos() g.write('${cur_line}${tmp}') } } diff --git a/vlib/v/tests/conditions/ifs/if_expr_with_condition_using_tmp_var_test.v b/vlib/v/tests/conditions/ifs/if_expr_with_condition_using_tmp_var_test.v new file mode 100644 index 000000000..0df2fe12f --- /dev/null +++ b/vlib/v/tests/conditions/ifs/if_expr_with_condition_using_tmp_var_test.v @@ -0,0 +1,27 @@ +fn option() ?int { + return 10 +} + +fn result() !int { + return 10 +} + +fn test_if_expr_with_condition_using_tmp_var() { + num := if option()? == 10 { + 0 + } else if option()? == 15 { + 1 + } else { + 2 + } + assert num == 0 + + num2 := if result()! == 10 { + 0 + } else if result()! == 15 { + 1 + } else { + 2 + } + assert num2 == 0 +} -- 2.39.5