Skip to content

Commit 50fd4fd

Browse files
authored
cgen: fix if expr with condition that requires temporary variable (fix #19584) (fix #23903) (#25621)
1 parent 92a170a commit 50fd4fd

File tree

2 files changed

+48
-4
lines changed

2 files changed

+48
-4
lines changed

vlib/v/gen/c/if.v

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,9 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
197197
mut cur_line := ''
198198
mut raw_state := false
199199
tmp_if_option_type := g.last_if_option_type
200+
mut exit_label := ''
200201
if needs_tmp_var {
202+
exit_label = g.new_tmp_var()
201203
mut styp := g.styp(node.typ)
202204
if g.inside_if_option || node.typ.has_flag(.option) {
203205
raw_state = g.inside_if_option
@@ -235,9 +237,11 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
235237
g.write('${styp} ')
236238
}
237239
g.writeln('${tmp}; /* if prepend */')
240+
g.set_current_pos_as_last_stmt_pos()
238241
}
239242
if g.infix_left_var_name.len > 0 {
240243
g.writeln('if (${g.infix_left_var_name}) {')
244+
g.set_current_pos_as_last_stmt_pos()
241245
g.indent++
242246
}
243247
} else if node.is_expr || g.inside_ternary != 0 {
@@ -303,11 +307,17 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
303307
}
304308
mut branch_cond_var_names := []string{}
305309
for i, branch in node.branches {
310+
is_else := i == node.branches.len - 1 && node.has_else
306311
if i > 0 {
307-
g.write('} else ')
312+
if needs_tmp_var {
313+
g.writeln('};')
314+
g.set_current_pos_as_last_stmt_pos()
315+
} else {
316+
g.write('} else ')
317+
}
308318
}
309319
// if last branch is `else {`
310-
if i == node.branches.len - 1 && node.has_else {
320+
if is_else {
311321
g.writeln('{')
312322
// define `err` for the last branch after a `if val := opt {...}' guard
313323
if is_guard && guard_idx == i - 1 {
@@ -475,6 +485,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
475485
}
476486
g.stmts_with_tmp_var(branch.stmts, tmp)
477487
g.expected_cast_type = prev_expected_cast_type
488+
if !is_else && (branch.stmts.len > 0
489+
&& branch.stmts[branch.stmts.len - 1] !in [ast.Return, ast.BranchStmt]) {
490+
g.writeln('\tgoto ${exit_label};')
491+
}
478492
} else {
479493
// restore if_expr stmt header pos
480494
stmt_pos := g.nth_stmt_pos(0)
@@ -484,15 +498,18 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
484498
}
485499
if node.branches.len > 0 {
486500
g.writeln('}')
487-
g.set_current_pos_as_last_stmt_pos()
501+
if !needs_tmp_var {
502+
g.set_current_pos_as_last_stmt_pos()
503+
}
488504
}
489505
if needs_tmp_var {
490506
if g.infix_left_var_name.len > 0 {
491507
g.indent--
492508
g.writeln('}')
493-
g.set_current_pos_as_last_stmt_pos()
494509
}
495510
g.empty_line = false
511+
g.writeln('\t${exit_label}: {};')
512+
g.set_current_pos_as_last_stmt_pos()
496513
g.write('${cur_line}${tmp}')
497514
}
498515
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
fn option() ?int {
2+
return 10
3+
}
4+
5+
fn result() !int {
6+
return 10
7+
}
8+
9+
fn test_if_expr_with_condition_using_tmp_var() {
10+
num := if option()? == 10 {
11+
0
12+
} else if option()? == 15 {
13+
1
14+
} else {
15+
2
16+
}
17+
assert num == 0
18+
19+
num2 := if result()! == 10 {
20+
0
21+
} else if result()! == 15 {
22+
1
23+
} else {
24+
2
25+
}
26+
assert num2 == 0
27+
}

0 commit comments

Comments
 (0)