From 3f279cc6056edf02404c8c609f107756a381bed5 Mon Sep 17 00:00:00 2001 From: kbkpbot Date: Mon, 22 Dec 2025 01:29:18 +0800 Subject: [PATCH] cgen: fix cast() generic type bug (fix #26065) (#26066) --- vlib/v/gen/c/cgen.v | 44 +++++++++++++++---------------- vlib/v/tests/bool_cast_int_test.v | 7 +++++ 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 68f2c7af4..32b5a0a75 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5662,51 +5662,51 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { return } if node_typ_is_option && node.expr is ast.None { - g.gen_option_error(node.typ, node.expr) + g.gen_option_error(node_typ, node.expr) } else if node.expr is ast.Ident && g.comptime.is_comptime_variant_var(node.expr) { g.expr_with_cast(node.expr, g.type_resolver.get_ct_type_or_default('${g.comptime.comptime_for_variant_var}.typ', ast.void_type), node_typ) } else if node_typ_is_option { - g.expr_with_opt(node.expr, expr_type, node.typ) + g.expr_with_opt(node.expr, expr_type, node_typ) } else { g.expr_with_cast(node.expr, expr_type, node_typ) } - } else if !node_typ_is_option && !node.typ.is_ptr() && sym.info is ast.Struct + } else if !node_typ_is_option && !node_typ.is_ptr() && sym.info is ast.Struct && !sym.info.is_typedef { // deprecated, replaced by Struct{...exr} - styp := g.styp(node.typ) + styp := g.styp(node_typ) g.write('*((${styp} *)(&') g.expr(node.expr) g.write('))') - } else if sym.kind == .alias && g.table.final_sym(node.typ).kind == .array_fixed { + } else if sym.kind == .alias && g.table.final_sym(node_typ).kind == .array_fixed { if node_typ_is_option { - g.expr_with_opt(node.expr, expr_type, node.typ) + g.expr_with_opt(node.expr, expr_type, node_typ) } else { if node.expr is ast.ArrayInit && g.assign_op != .decl_assign && !g.inside_const { g.write('(${g.styp(node.expr.typ)})') } g.expr(node.expr) } - } else if (expr_type == ast.bool_type && node.typ.is_int()) || node.typ == ast.bool_type { + } else if (expr_type == ast.bool_type && node_typ.is_int()) || node_typ == ast.bool_type { if node_typ_is_option { - g.expr_with_opt(node.expr, expr_type, node.typ) + g.expr_with_opt(node.expr, expr_type, node_typ) } else { if (g.pref.translated || g.file.is_translated) && g.inside_global_decl { - styp := g.styp(node.typ) + styp := g.styp(node_typ) g.write('(${styp})') g.expr(node.expr) - } else if node.typ == ast.bool_type && expr_type == ast.bool_type { + } else if node_typ == ast.bool_type && expr_type == ast.bool_type { g.expr(node.expr) } else { // due to tcc(0.9.27) bug, can't use `(cond)?1:0` here - styp := g.styp(node.typ) + styp := g.styp(node_typ) g.write('(${styp}[]){(') g.expr(node.expr) g.write(')?1:0}[0]') } } } else { - styp := g.styp(node.typ) + styp := g.styp(node_typ) if (g.pref.translated || g.file.is_translated) && sym.kind == .function { // TODO: handle the type in fn casts, not just exprs /* @@ -5721,14 +5721,14 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { if sym.kind != .alias || (sym.info is ast.Alias && !sym.info.parent_type.has_flag(.option) && sym.info.parent_type !in [expr_type, ast.string_type]) { - if sym.kind == .string && !node.typ.is_ptr() { + if sym.kind == .string && !node_typ.is_ptr() { cast_label = '*(string*)&' - } else if !(g.is_cc_msvc && g.styp(node.typ) == g.styp(expr_type)) { + } else if !(g.is_cc_msvc && g.styp(node_typ) == g.styp(expr_type)) { cast_label = '(${styp})' } } if node_typ_is_option && node.expr is ast.None { - g.gen_option_error(node.typ, node.expr) + g.gen_option_error(node_typ, node.expr) } else if node_typ_is_option { if sym.info is ast.Alias { if sym.info.parent_type.has_flag(.option) { @@ -5744,12 +5744,12 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { g.writeln('builtin___option_ok(&(${g.styp(parent_type)}[]) { ${tmp_var2} }, (${option_name}*)&${tmp_var}, sizeof(${g.styp(parent_type)}));') g.write2(cur_stmt, tmp_var) } else if node.expr_type.has_flag(.option) { - g.expr_opt_with_alias(node.expr, expr_type, node.typ) + g.expr_opt_with_alias(node.expr, expr_type, node_typ) } else { - g.expr_with_opt(node.expr, expr_type, node.typ) + g.expr_with_opt(node.expr, expr_type, node_typ) } } else { - g.expr_with_opt(node.expr, expr_type, node.typ) + g.expr_with_opt(node.expr, expr_type, node_typ) } } else if sym.info is ast.Alias && sym.info.parent_type.has_flag(.option) { g.expr_with_opt(node.expr, expr_type, sym.info.parent_type) @@ -5768,18 +5768,18 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) { g.inside_assign_fn_var = g.table.final_sym(expr_type).kind == .function g.write('(') if node.expr is ast.Ident { - if !node.typ.is_ptr() && node.expr_type.is_ptr() && node.expr.obj is ast.Var + if !node_typ.is_ptr() && node.expr_type.is_ptr() && node.expr.obj is ast.Var && node.expr.obj.smartcasts.len > 0 { g.write('*'.repeat(node.expr_type.nr_muls())) } } - if sym.kind == .alias && g.table.final_sym(node.typ).kind == .string { - ptr_cnt := node.typ.nr_muls() - expr_type.nr_muls() + if sym.kind == .alias && g.table.final_sym(node_typ).kind == .string { + ptr_cnt := node_typ.nr_muls() - expr_type.nr_muls() if ptr_cnt > 0 { g.write('&'.repeat(ptr_cnt)) } } - if node.typ == ast.voidptr_type && node.expr is ast.ArrayInit + if node_typ == ast.voidptr_type && node.expr is ast.ArrayInit && (node.expr as ast.ArrayInit).is_fixed { expr_styp := g.styp(node.expr_type) g.write('(${expr_styp})') diff --git a/vlib/v/tests/bool_cast_int_test.v b/vlib/v/tests/bool_cast_int_test.v index 9e3cb092c..31ccacd50 100644 --- a/vlib/v/tests/bool_cast_int_test.v +++ b/vlib/v/tests/bool_cast_int_test.v @@ -1,5 +1,10 @@ module main +fn generic_asm[T](var &T) T { + ret := unsafe { T(14) } + return ret +} + fn test_main() { v1 := unsafe { bool(1) } v10 := unsafe { bool(10) } @@ -11,4 +16,6 @@ fn test_main() { assert int(v2) == 0 v3 := true assert int(v3) == 1 + + assert generic_asm[bool](v1) == true } -- 2.39.5