mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
v.gen.c: fix error of if_expr in infix_expr (#11200)
This commit is contained in:
parent
d7490abe19
commit
90b052b1db
@ -168,13 +168,14 @@ mut:
|
||||
// TypeOne, TypeTwo {}
|
||||
// where an aggregate (at least two types) is generated
|
||||
// sum type deref needs to know which index to deref because unions take care of the correct field
|
||||
aggregate_type_idx int
|
||||
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned
|
||||
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
||||
timers &util.Timers = util.new_timers(false)
|
||||
force_main_console bool // true when [console] used on fn main()
|
||||
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
|
||||
obf_table map[string]string
|
||||
aggregate_type_idx int
|
||||
returned_var_name string // to detect that a var doesn't need to be freed since it's being returned
|
||||
branch_parent_pos int // used in BranchStmt (continue/break) for autofree stop position
|
||||
infix_left_var_name string // a && if expr
|
||||
timers &util.Timers = util.new_timers(false)
|
||||
force_main_console bool // true when [console] used on fn main()
|
||||
as_cast_type_names map[string]string // table for type name lookup in runtime (for __as_cast)
|
||||
obf_table map[string]string
|
||||
// main_fn_decl_node ast.FnDecl
|
||||
expected_cast_type ast.Type // for match expr of sumtypes
|
||||
defer_vars []string
|
||||
@ -4626,6 +4627,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
cur_line = g.go_before_stmt(0)
|
||||
g.empty_line = true
|
||||
g.writeln('$styp $tmp; /* if prepend */')
|
||||
if g.infix_left_var_name.len > 0 {
|
||||
g.writeln('if ($g.infix_left_var_name) {')
|
||||
g.indent++
|
||||
}
|
||||
} else if node.is_expr || g.inside_ternary != 0 {
|
||||
g.inside_ternary++
|
||||
g.write('(')
|
||||
@ -4739,6 +4744,10 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
|
||||
}
|
||||
g.writeln('}')
|
||||
if needs_tmp_var {
|
||||
if g.infix_left_var_name.len > 0 {
|
||||
g.indent--
|
||||
g.writeln('}')
|
||||
}
|
||||
g.empty_line = false
|
||||
g.write('$cur_line $tmp')
|
||||
}
|
||||
|
@ -33,6 +33,9 @@ fn (mut g Gen) infix_expr(node ast.InfixExpr) {
|
||||
.left_shift {
|
||||
g.infix_expr_left_shift_op(node)
|
||||
}
|
||||
.and, .logical_or {
|
||||
g.infix_expr_and_or_op(node)
|
||||
}
|
||||
else {
|
||||
// `x & y == 0` => `(x & y) == 0` in C
|
||||
need_par := node.op in [.amp, .pipe, .xor]
|
||||
@ -499,28 +502,34 @@ fn (mut g Gen) infix_expr_left_shift_op(node ast.InfixExpr) {
|
||||
}
|
||||
}
|
||||
|
||||
// infix_expr_and_or_op generates code for `&&` and `||`
|
||||
fn (mut g Gen) infix_expr_and_or_op(node ast.InfixExpr) {
|
||||
if node.right is ast.IfExpr {
|
||||
// b := a && if true { a = false ...} else {...}
|
||||
if g.need_tmp_var_in_if(node.right) {
|
||||
tmp := g.new_tmp_var()
|
||||
cur_line := g.go_before_stmt(0).trim_space()
|
||||
g.empty_line = true
|
||||
g.write('bool $tmp = (')
|
||||
g.expr(node.left)
|
||||
g.writeln(');')
|
||||
g.stmt_path_pos << g.out.len
|
||||
g.write('$cur_line $tmp $node.op.str() ')
|
||||
g.infix_left_var_name = if node.op == .and { tmp } else { '!$tmp' }
|
||||
g.expr(node.right)
|
||||
g.infix_left_var_name = ''
|
||||
return
|
||||
}
|
||||
}
|
||||
g.gen_plain_infix_expr(node)
|
||||
}
|
||||
|
||||
// gen_plain_infix_expr generates basic code for infix expressions,
|
||||
// without any overloading of any kind
|
||||
// i.e. v`a + 1` => c`a + 1`
|
||||
// It handles auto dereferencing of variables, as well as automatic casting
|
||||
// (see Gen.expr_with_cast for more details)
|
||||
fn (mut g Gen) gen_plain_infix_expr(node ast.InfixExpr) {
|
||||
if node.left is ast.Ident && node.right is ast.IfExpr {
|
||||
// b := a && if true { a = false ...} else {...}
|
||||
if g.need_tmp_var_in_if(node.right) {
|
||||
tmp := g.new_tmp_var()
|
||||
styp := g.typ(node.left_type)
|
||||
cur_line := g.go_before_stmt(0)
|
||||
g.empty_line = true
|
||||
g.write('$styp $tmp = ')
|
||||
g.expr(node.left)
|
||||
g.writeln(';')
|
||||
g.stmt_path_pos << g.out.len
|
||||
g.write('$cur_line $tmp $node.op.str() ')
|
||||
g.expr(node.right)
|
||||
return
|
||||
}
|
||||
}
|
||||
if node.left_type.is_ptr() && node.left.is_auto_deref_var() {
|
||||
g.write('*')
|
||||
}
|
||||
|
13
vlib/v/tests/valgrind/if_expr_skip.v
Normal file
13
vlib/v/tests/valgrind/if_expr_skip.v
Normal file
@ -0,0 +1,13 @@
|
||||
fn main() {
|
||||
mut a := false
|
||||
b := a && if true {
|
||||
a = true
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
println(b)
|
||||
assert b == false
|
||||
println(a)
|
||||
assert a == false
|
||||
}
|
Loading…
Reference in New Issue
Block a user