Skip to content

Commit f4aa139

Browse files
authored
cgen: fix codegen for nested if on return (fix #23723) (#23729)
1 parent ae899e6 commit f4aa139

File tree

3 files changed

+65
-6
lines changed

3 files changed

+65
-6
lines changed

vlib/v/gen/c/cgen.v

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ mut:
161161
inside_global_decl bool
162162
inside_interface_deref bool
163163
last_tmp_call_var []string
164+
last_if_option_type ast.Type // stores the expected if type on nested if expr
164165
loop_depth int
165166
ternary_names map[string]string
166167
ternary_level_names map[string][]string
@@ -2068,7 +2069,8 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool {
20682069
styp = 'f64'
20692070
}
20702071
}
2071-
if stmt.typ.has_flag(.option) {
2072+
if stmt.typ.has_flag(.option)
2073+
|| (g.inside_if_option && stmt.expr is ast.IfExpr) {
20722074
g.writeln('')
20732075
g.write('${tmp_var} = ')
20742076
g.expr(stmt.expr)
@@ -2082,7 +2084,6 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool {
20822084
}
20832085
styp = g.base_type(ret_typ)
20842086
if stmt.expr is ast.CallExpr && stmt.expr.is_noreturn {
2085-
g.expr(stmt.expr)
20862087
g.writeln(';')
20872088
} else {
20882089
g.write('_option_ok(&(${styp}[]) { ')

vlib/v/gen/c/if.v

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -185,15 +185,26 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
185185
// easier to use a temp var, than do C tricks with commas, introduce special vars etc
186186
// (as it used to be done).
187187
// Always use this in -autofree, since ?: can have tmp expressions that have to be freed.
188-
needs_tmp_var := g.need_tmp_var_in_if(node)
188+
needs_tmp_var := g.inside_if_option || g.need_tmp_var_in_if(node)
189189
needs_conds_order := g.needs_conds_order(node)
190-
tmp := if node.typ != ast.void_type && needs_tmp_var { g.new_tmp_var() } else { '' }
190+
tmp := if g.inside_if_option || (node.typ != ast.void_type && needs_tmp_var) {
191+
g.new_tmp_var()
192+
} else {
193+
''
194+
}
191195
mut cur_line := ''
192196
mut raw_state := false
197+
tmp_if_option_type := g.last_if_option_type
193198
if needs_tmp_var {
194199
mut styp := g.styp(node.typ)
195-
if node.typ.has_flag(.option) {
200+
if g.inside_if_option || node.typ.has_flag(.option) {
196201
raw_state = g.inside_if_option
202+
if node.typ != ast.void_type {
203+
g.last_if_option_type = node.typ
204+
defer {
205+
g.last_if_option_type = tmp_if_option_type
206+
}
207+
}
197208
defer {
198209
g.inside_if_option = raw_state
199210
}
@@ -210,7 +221,13 @@ fn (mut g Gen) if_expr(node ast.IfExpr) {
210221
cur_line = g.go_before_last_stmt()
211222
g.empty_line = true
212223
if tmp != '' {
213-
g.writeln('${styp} ${tmp}; /* if prepend */')
224+
if node.typ == ast.void_type && g.last_if_option_type != 0 {
225+
// nested if on return stmt
226+
g.write2(g.styp(g.last_if_option_type), ' ')
227+
} else {
228+
g.write('${styp} ')
229+
}
230+
g.writeln('${tmp}; /* if prepend */')
214231
}
215232
if g.infix_left_var_name.len > 0 {
216233
g.writeln('if (${g.infix_left_var_name}) {')
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
struct Message {
2+
prio bool
3+
}
4+
5+
struct Throttler[T] {
6+
max_wait int
7+
mut:
8+
wait_counter int
9+
low_prio_requests []T
10+
high_prio_requests []T
11+
}
12+
13+
fn new_throttler[T](max_wait int) Throttler[T] {
14+
return Throttler[T]{max_wait, 0, []T{len: 1, init: T{}}, []T{len: 1, init: T{}}}
15+
}
16+
17+
fn pop[T](mut t Throttler[T]) ?T {
18+
if t.wait_counter <= t.max_wait {
19+
return if t.high_prio_requests.len > 10 {
20+
t.high_prio_requests.pop()
21+
} else {
22+
t.wait_counter = 0
23+
if t.low_prio_requests.len > 0 {
24+
t.low_prio_requests.pop()
25+
} else {
26+
none
27+
}
28+
}
29+
} else {
30+
return none
31+
}
32+
}
33+
34+
fn test_main() {
35+
c := chan Message{}
36+
mut throttler := new_throttler[Message](10)
37+
msg := pop(mut throttler) or { return }
38+
assert msg.str() == 'Message{
39+
prio: false
40+
}'
41+
}

0 commit comments

Comments
 (0)