1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

cgen: fix result/option breaks execution order in if statements (fix #16663) (#16778)

This commit is contained in:
yuyi 2022-12-28 16:26:39 +08:00 committed by GitHub
parent afdb09708e
commit b9996619d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 16 deletions

View File

@ -141,6 +141,17 @@ fn (mut g Gen) need_tmp_var_in_expr(expr ast.Expr) bool {
return false
}
fn (mut g Gen) needs_conds_order(node ast.IfExpr) bool {
if node.branches.len > 1 {
for branch in node.branches {
if g.need_tmp_var_in_expr(branch.cond) {
return true
}
}
}
return false
}
fn (mut g Gen) if_expr(node ast.IfExpr) {
if node.is_comptime {
g.comptime_if(node)
@ -153,6 +164,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
// (as it used to be done).
// Always use this in -autofree, since ?: can have tmp expressions that have to be freed.
needs_tmp_var := g.need_tmp_var_in_if(node)
needs_conds_order := g.needs_conds_order(node)
tmp := if needs_tmp_var { g.new_tmp_var() } else { '' }
mut cur_line := ''
mut raw_state := false
@ -224,6 +236,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
}
}
}
mut branch_cond_var_names := []string{}
for i, branch in node.branches {
if i > 0 {
g.write('} else ')
@ -302,6 +315,39 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
}
}
}
} else {
if i == 0 && node.branches.len > 1 && !needs_tmp_var && needs_conds_order {
cond_var_name := g.new_tmp_var()
line := g.go_before_stmt(0).trim_space()
g.empty_line = true
g.write('bool ${cond_var_name} = ')
g.expr(branch.cond)
g.writeln(';')
branch_cond_var_names << cond_var_name
g.set_current_pos_as_last_stmt_pos()
g.writeln(line)
g.writeln('if (${cond_var_name}) {')
} else if i > 0 && branch_cond_var_names.len > 0 && !needs_tmp_var && needs_conds_order {
cond_var_name := g.new_tmp_var()
line := g.go_before_stmt(0)
g.empty_line = true
g.writeln('bool ${cond_var_name};')
branch_cond := branch_cond_var_names.join(' || ')
g.writeln('if (!(${branch_cond})) {')
g.set_current_pos_as_last_stmt_pos()
g.indent++
g.write('${cond_var_name} = ')
prev_is_autofree := g.is_autofree
g.is_autofree = false
g.expr(branch.cond)
g.is_autofree = prev_is_autofree
g.writeln(';')
g.indent--
g.writeln('}')
branch_cond_var_names << cond_var_name
g.set_current_pos_as_last_stmt_pos()
g.write(line)
g.writeln('if (${cond_var_name}) {')
} else {
mut no_needs_par := false
if branch.cond is ast.InfixExpr {
@ -322,6 +368,7 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
g.writeln(') {')
}
}
}
if needs_tmp_var {
prev_expected_cast_type := g.expected_cast_type
if node.is_expr

View File

@ -0,0 +1,4 @@
test
f1
f2
-> 02

View File

@ -0,0 +1,38 @@
fn f1() bool {
println('f1')
return false
}
fn f2() bool {
println('f2')
return true
}
fn f3() !bool {
println('f3')
return false
}
fn f4() bool {
println('f4')
return true
}
fn test() ! {
println('test')
if f1() {
println('-> 01')
} else if f2() {
println('-> 02')
} else if f2() && f3()! {
println('-> 03')
} else if f4() {
println('-> 04')
} else {
println('-> 05')
}
}
fn main() {
test() or { panic(err) }
}