Skip to content

Commit e8d98e1

Browse files
authored
cgen: clean code in return stmt (fix #25968) (#26118)
1 parent 557ca40 commit e8d98e1

3 files changed

Lines changed: 70 additions & 52 deletions

File tree

‎vlib/v/gen/c/cgen.v‎

Lines changed: 36 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,10 +2359,16 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
23592359
panic('cgen: parameter `ret_typ` of function `expr_with_tmp_var()` must be an Option or Result')
23602360
}
23612361

2362+
assign_op := g.assign_op
2363+
defer {
2364+
g.assign_op = assign_op
2365+
}
2366+
g.assign_op = .unknown
23622367
stmt_str := g.go_before_last_stmt().trim_space()
23632368
mut styp := g.base_type(ret_typ)
23642369
g.empty_line = true
23652370
final_expr_sym := g.table.final_sym(expr_typ)
2371+
mut expected_type := ret_typ
23662372

23672373
if final_expr_sym.kind == .none {
23682374
g.write('${g.styp(ret_typ)} ${tmp_var} = ')
@@ -2435,11 +2441,6 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
24352441
&& (expr.right as ast.StructInit).init_fields.len == 0 {
24362442
g.write('builtin___option_none(&(${styp}[]) { ')
24372443
} else if final_expr_sym.kind == .array_fixed {
2438-
assign_op := g.assign_op
2439-
defer(fn) {
2440-
g.assign_op = assign_op
2441-
}
2442-
g.assign_op = .unknown
24432444
expr_is_fixed_array_var = true
24442445
info := final_expr_sym.array_fixed_info()
24452446
mut no_cast := false
@@ -2486,10 +2487,29 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
24862487
}
24872488
}
24882489
} else {
2489-
g.write('builtin___result_ok(&(${styp}[]) { ')
2490+
if final_expr_sym.kind == .array_fixed {
2491+
expr_is_fixed_array_var = true
2492+
info := final_expr_sym.array_fixed_info()
2493+
mut no_cast := false
2494+
if expr in [ast.CastExpr, ast.CallExpr, ast.Ident, ast.SelectorExpr] {
2495+
no_cast = true
2496+
}
2497+
elem_sym := g.table.sym(info.elem_type)
2498+
if elem_sym.kind == .struct {
2499+
expr_is_fixed_array_var = false
2500+
g.write('builtin___result_ok(&(${styp}[]) { ')
2501+
} else if no_cast {
2502+
g.write('builtin___result_ok(')
2503+
} else {
2504+
g.write('builtin___result_ok((${g.styp(final_expr_sym.idx)})')
2505+
}
2506+
} else {
2507+
g.write('builtin___result_ok(&(${styp}[]) { ')
2508+
expected_type = ret_typ.clear_flag(.result)
2509+
}
24902510
}
24912511
if !already_generated {
2492-
g.expr_with_cast(expr, expr_typ, ret_typ)
2512+
g.expr_with_cast(expr, expr_typ, expected_type)
24932513
}
24942514

24952515
if fn_option_clone {
@@ -2504,7 +2524,11 @@ fn (mut g Gen) expr_with_tmp_var(expr ast.Expr, expr_typ ast.Type, ret_typ ast.T
25042524
g.writeln(' }, (${option_name}*)(&${tmp_var}), sizeof(${styp}));')
25052525
}
25062526
} else {
2507-
g.writeln(' }, (${result_name}*)(&${tmp_var}), sizeof(${styp}));')
2527+
if expr_is_fixed_array_var {
2528+
g.writeln(', (${result_name}*)(&${tmp_var}), sizeof(${styp}));')
2529+
} else {
2530+
g.writeln(' }, (${result_name}*)(&${tmp_var}), sizeof(${styp}));')
2531+
}
25082532
}
25092533
g.set_current_pos_as_last_stmt_pos()
25102534
}
@@ -6444,17 +6468,6 @@ fn (mut g Gen) return_stmt(node ast.Return) {
64446468
type0.has_flag(.option)
64456469
}
64466470
}
6447-
if fn_return_is_option && !expr_type_is_opt && return_sym.name != option_name {
6448-
g.expr_with_tmp_var(expr0, type0, fn_ret_type, tmpvar, false)
6449-
g.writeln('')
6450-
g.write_defer_stmts_when_needed(node.scope, true, node.pos)
6451-
if g.is_autofree {
6452-
g.detect_used_var_on_return(expr0)
6453-
}
6454-
g.autofree_scope_vars(node.pos.pos - 1, node.pos.line_nr, true)
6455-
g.writeln('return ${tmpvar};')
6456-
return
6457-
}
64586471
expr_type_is_result := match expr0 {
64596472
ast.CallExpr {
64606473
expr0.return_type.has_flag(.result) && expr0.or_block.kind == .absent
@@ -6463,38 +6476,10 @@ fn (mut g Gen) return_stmt(node ast.Return) {
64636476
type0.has_flag(.result)
64646477
}
64656478
}
6466-
if fn_return_is_result && !expr_type_is_result && return_sym.name != result_name {
6467-
g.writeln('${ret_typ} ${tmpvar} = {0};')
6468-
if fn_return_is_fixed_array && expr0 !is ast.ArrayInit
6469-
&& g.table.final_sym(type0).kind == .array_fixed {
6470-
styp := g.styp(fn_ret_type.clear_option_and_result())
6471-
g.write('memcpy(${tmpvar}.data, ')
6472-
if expr0 in [ast.CallExpr, ast.StructInit] {
6473-
g.expr_with_opt(expr0, type0, fn_ret_type)
6474-
g.write('.data')
6475-
} else {
6476-
g.expr(expr0)
6477-
}
6478-
g.writeln(', sizeof(${styp}));')
6479-
} else {
6480-
styp := g.base_type(fn_ret_type)
6481-
g.write('builtin___result_ok(&(${styp}[]) { ')
6482-
if !fn_ret_type.is_ptr() && type0.is_ptr() {
6483-
if !((expr0 is ast.Ident && !g.is_amp) || sym.kind == .interface) {
6484-
g.write('*')
6485-
}
6486-
}
6487-
if fn_ret_type.has_flag(.option) {
6488-
g.expr_with_opt(expr0, type0, fn_ret_type.clear_flag(.result))
6489-
} else if return_sym.kind == .array_fixed && expr0 !is ast.ArrayInit {
6490-
info := return_sym.info as ast.ArrayFixed
6491-
g.fixed_array_var_init(g.expr_string(expr0), expr0.is_auto_deref_var(),
6492-
info.elem_type, info.size)
6493-
} else {
6494-
g.expr_with_cast(expr0, type0, fn_ret_type.clear_flag(.result))
6495-
}
6496-
g.writeln(' }, (${result_name}*)(&${tmpvar}), sizeof(${styp}));')
6497-
}
6479+
if (fn_return_is_option && !expr_type_is_opt && return_sym.name != option_name)
6480+
|| (fn_return_is_result && !expr_type_is_result && return_sym.name != result_name) {
6481+
g.expr_with_tmp_var(expr0, type0, fn_ret_type, tmpvar, false)
6482+
g.writeln('')
64986483
g.write_defer_stmts_when_needed(node.scope, true, node.pos)
64996484
if g.is_autofree {
65006485
g.detect_used_var_on_return(expr0)

‎vlib/v/gen/c/testdata/autofree_toml.c.must_have‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
_result_toml__scanner__Scanner_ptr toml__scanner__new_scanner(toml__scanner__Config config) {
2-
_result_toml__scanner__Scanner_ptr _t3 = {0};
2+
_result_toml__scanner__Scanner_ptr _t3;
33
builtin___result_ok(&(toml__scanner__Scanner*[]) { s }, (_result*)(&_t3), sizeof(toml__scanner__Scanner*));
44
return _t3;
55
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import strconv
2+
3+
pub fn valid_triangle(a u8, b u8, c u8) ![3]u8 {
4+
if int(a) + int(b) <= int(c) {
5+
return error('Invalid: a + b <= c')
6+
}
7+
if int(b) + int(c) <= int(a) {
8+
return error('Invalid: b + c <= a')
9+
}
10+
if int(c) + int(a) <= int(b) {
11+
return error('Invalid: c + a <= b')
12+
}
13+
return [a, b, c]!
14+
}
15+
16+
pub fn triangle_from_string(sides string) ![3]u8 {
17+
s := sides.split(',')
18+
if s.len != 3 {
19+
return error('Invalid: number of sides')
20+
}
21+
a := strconv.atou8(s[0])!
22+
b := strconv.atou8(s[1])!
23+
c := strconv.atou8(s[2])!
24+
// warning: don't append `!` to next call
25+
// will confuse with fixed and return `garbage`.
26+
return valid_triangle(a, b, c)!
27+
}
28+
29+
fn test_main() {
30+
assert triangle_from_string('3,4,5')![0] == 3
31+
assert triangle_from_string('3,4,5')![1] == 4
32+
assert triangle_from_string('3,4,5')![2] == 5
33+
}

0 commit comments

Comments
 (0)