Skip to content

Commit

Permalink
cgen: fix callexpr or-expr codegen on const decl (fix vlang#23029) (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
felipensp authored Dec 2, 2024
1 parent f3d0c53 commit 3036a5a
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 19 deletions.
28 changes: 10 additions & 18 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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:
Expand Down Expand Up @@ -6184,20 +6182,17 @@ 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 {
has_unwrap_opt_res = field.expr.left.or_block.kind != .absent
} 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)
}
}
}
Expand Down Expand Up @@ -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)
Expand All @@ -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 {
Expand Down
10 changes: 9 additions & 1 deletion vlib/v/gen/c/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 11 additions & 0 deletions vlib/v/tests/fns/const_call_or_expr_test.v
Original file line number Diff line number Diff line change
@@ -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 == ''
}

0 comments on commit 3036a5a

Please sign in to comment.