Skip to content

Commit 104034f

Browse files
authored
cgen: fix default value in if/else or block (fix #26002) (#26020)
1 parent 6623dbf commit 104034f

2 files changed

Lines changed: 114 additions & 4 deletions

File tree

‎vlib/v/gen/c/if.v‎

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,13 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
200200
mut exit_label := ''
201201
if needs_tmp_var {
202202
exit_label = g.new_tmp_var()
203-
mut styp := g.styp(node.typ)
204-
if g.inside_if_option || node.typ.has_flag(.option) {
203+
node_typ := if g.inside_or_block {
204+
node.typ.clear_option_and_result()
205+
} else {
206+
node.typ
207+
}
208+
mut styp := g.styp(node_typ)
209+
if (g.inside_if_option || node_typ.has_flag(.option)) && !g.inside_or_block {
205210
raw_state = g.inside_if_option
206211
if node.typ != ast.void_type {
207212
g.last_if_option_type = node.typ
@@ -214,15 +219,15 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
214219
}
215220
g.inside_if_option = true
216221
styp = styp.replace('*', '_ptr')
217-
} else if node.typ.has_flag(.result) {
222+
} else if node_typ.has_flag(.result) && !g.inside_or_block {
218223
raw_state = g.inside_if_result
219224
defer(fn) {
220225
g.inside_if_result = raw_state
221226
}
222227
g.inside_if_result = true
223228
styp = styp.replace('*', '_ptr')
224229
} else {
225-
g.last_if_option_type = node.typ
230+
g.last_if_option_type = node_typ
226231
defer(fn) {
227232
g.last_if_option_type = tmp_if_option_type
228233
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
fn foo(a int) !int {
2+
if a < 0 {
3+
return error('foo')
4+
}
5+
return a
6+
}
7+
8+
fn bar(a int) !int {
9+
return foo(a) or {
10+
if a < 0 {
11+
-1
12+
} else {
13+
return error('bar')
14+
}
15+
}
16+
}
17+
18+
fn baz(a int) !int {
19+
return foo(a) or {
20+
if a < 0 {
21+
-1
22+
} else {
23+
-2
24+
}
25+
}
26+
}
27+
28+
fn qux(a int) ?int {
29+
if a < 0 {
30+
return none
31+
}
32+
return a
33+
}
34+
35+
fn quux(a int) ?int {
36+
return qux(a) or {
37+
if a < 0 {
38+
-1
39+
} else {
40+
return none
41+
}
42+
}
43+
}
44+
45+
fn test_if_expr_in_result_or_block_with_return() {
46+
assert bar(0)! == 0
47+
assert bar(-1)! == -1
48+
assert bar(1)! == 1
49+
}
50+
51+
fn test_if_expr_in_result_or_block_simple() {
52+
assert baz(0)! == 0
53+
assert baz(-1)! == -1
54+
assert baz(1)! == 1
55+
}
56+
57+
fn test_if_expr_in_option_or_block_with_return() {
58+
assert quux(0)? == 0
59+
assert quux(-1)? == -1
60+
assert quux(1)? == 1
61+
}
62+
63+
fn test_nested_if_in_or_block() {
64+
get_val := fn (x int) !int {
65+
if x < 0 {
66+
return error('negative')
67+
}
68+
return x * 2
69+
}
70+
result := get_val(-5) or {
71+
if true {
72+
if false {
73+
100
74+
} else {
75+
-10
76+
}
77+
} else {
78+
200
79+
}
80+
}
81+
assert result == -10
82+
}
83+
84+
fn test_if_expr_with_multiple_branches_in_or_block() {
85+
compute := fn (x int) !int {
86+
if x == 0 {
87+
return error('zero')
88+
}
89+
return x
90+
}
91+
val := compute(0) or {
92+
match err.msg() {
93+
'zero' {
94+
1
95+
}
96+
'negative' {
97+
2
98+
}
99+
else {
100+
3
101+
}
102+
}
103+
}
104+
assert val == 1
105+
}

0 commit comments

Comments
 (0)