From 3036a5afc68563e45443274e15cc0389c00ccf82 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 2 Dec 2024 02:17:59 -0300 Subject: [PATCH] cgen: fix callexpr or-expr codegen on const decl (fix #23029) (#23043) --- vlib/v/gen/c/cgen.v | 28 ++++++++-------------- vlib/v/gen/c/fn.v | 10 +++++++- vlib/v/tests/fns/const_call_or_expr_test.v | 11 +++++++++ 3 files changed, 30 insertions(+), 19 deletions(-) create mode 100644 vlib/v/tests/fns/const_call_or_expr_test.v diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 0c7075bae..b9e54cd18 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -6119,8 +6119,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { g.const_decl_init_later_msvc_string_fixed_array(field.mod, name, field.expr, field.typ) } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, - false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) } } ast.StringLiteral { @@ -6136,15 +6135,14 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { ast.CallExpr { if field.expr.return_type.has_flag(.option) || field.expr.return_type.has_flag(.result) { + old_inside_const_opt_or_res := g.inside_const_opt_or_res g.inside_const_opt_or_res = true unwrap_opt_res := field.expr.or_block.kind != .absent - g.const_decl_init_later(field.mod, name, field.expr, field.typ, unwrap_opt_res, - unwrap_opt_res) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, unwrap_opt_res) + g.inside_const_opt_or_res = old_inside_const_opt_or_res } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, - false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) } - g.inside_const_opt_or_res = false } else { // Note: -usecache uses prebuilt modules, each compiled with: @@ -6184,8 +6182,7 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { continue } } - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, - false) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, false) } else if field.expr is ast.InfixExpr { mut has_unwrap_opt_res := false if field.expr.left is ast.CallExpr { @@ -6193,11 +6190,9 @@ fn (mut g Gen) const_decl(node ast.ConstDecl) { } else if field.expr.right is ast.CallExpr { has_unwrap_opt_res = field.expr.right.or_block.kind != .absent } - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, - has_unwrap_opt_res) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, has_unwrap_opt_res) } else { - g.const_decl_init_later(field.mod, name, field.expr, field.typ, false, - true) + g.const_decl_init_later(field.mod, name, field.expr, field.typ, true) } } } @@ -6359,8 +6354,7 @@ fn (mut g Gen) c_const_name(name string) string { return if g.pref.translated && !g.is_builtin_mod { name } else { '_const_${name}' } } -fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ ast.Type, unwrap_option bool, - surround_cbr bool) { +fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ ast.Type, surround_cbr bool) { // Initialize more complex consts in `void _vinit/2{}` // (C doesn't allow init expressions that can't be resolved at compile time). mut styp := g.styp(typ) @@ -6370,9 +6364,7 @@ fn (mut g Gen) const_decl_init_later(mod string, name string, expr ast.Expr, typ if surround_cbr { init.writeln('{') } - if unwrap_option { - init.writeln(g.expr_string_surround('\t${cname} = *(${styp}*)', expr, '.data;')) - } else if expr is ast.ArrayInit && (expr as ast.ArrayInit).has_index { + if expr is ast.ArrayInit && (expr as ast.ArrayInit).has_index { init.writeln(g.expr_string_surround('\tmemcpy(&${cname}, &', expr, ', sizeof(${styp}));')) } else if expr is ast.CallExpr && g.table.final_sym(g.unwrap_generic((expr as ast.CallExpr).return_type)).kind == .array_fixed { diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index d2f3eb59b..a490f7f58 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -949,6 +949,10 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { tmp_opt := if gen_or || gen_keep_alive { if g.inside_curry_call && g.last_tmp_call_var.len > 0 { g.last_tmp_call_var.pop() + } else if !g.inside_or_block { + new_tmp := g.new_tmp_var() + g.last_tmp_call_var << new_tmp + new_tmp } else { g.new_tmp_var() } @@ -1031,7 +1035,11 @@ fn (mut g Gen) call_expr(node ast.CallExpr) { g.write('\n ${cur_line}') } } else { - g.write('\n ${cur_line} ${tmp_opt}') + if !g.inside_or_block && g.last_tmp_call_var.len > 0 { + g.write('\n\t*(${unwrapped_styp}*)${g.last_tmp_call_var.pop()}.data = ${cur_line}(*(${unwrapped_styp}*)${tmp_opt}.data)') + } else { + g.write('\n ${cur_line}(*(${unwrapped_styp}*)${tmp_opt}.data)') + } } } } else if gen_keep_alive { diff --git a/vlib/v/tests/fns/const_call_or_expr_test.v b/vlib/v/tests/fns/const_call_or_expr_test.v new file mode 100644 index 000000000..6dc49a753 --- /dev/null +++ b/vlib/v/tests/fns/const_call_or_expr_test.v @@ -0,0 +1,11 @@ +import os + +const vdir = os.getenv_opt('VDIR') or { os.dir(os.getenv_opt('VEXE') or { os.getwd() }) } +const vdir2 = os.getenv_opt('NON_EXISTENT') +const vdir3 = os.getenv_opt('NON_EXISTENT') or { '' } + +fn test_main() { + assert vdir.len > 0 + assert vdir2 == none + assert vdir3 == '' +} -- 2.39.5