From c3a2e9b5c4518fc978cbde11b869909b3c443c2a Mon Sep 17 00:00:00 2001 From: kalapalo Date: Tue, 21 Jul 2020 20:28:49 -0400 Subject: [PATCH] cgen: fix sum type assignment with pointers (#5868) --- vlib/v/gen/cgen.v | 30 ++++++++++++++++++++++++------ vlib/v/gen/fn.v | 4 +++- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 70a2995145..7af97a19ea 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -988,12 +988,26 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type, expected_type table.Type) { // cast to sum type if expected_type != table.void_type { - if g.table.sumtype_has_variant(expected_type, got_type) { - got_sym := g.table.get_type_symbol(got_type) - got_styp := g.typ(got_type) + expected_is_ptr := expected_type.is_ptr() + expected_deref_type := if expected_is_ptr { expected_type.deref() } else { expected_type } + got_is_ptr := got_type.is_ptr() + got_deref_type := if got_is_ptr { got_type.deref() } else { got_type } + if g.table.sumtype_has_variant(expected_deref_type, got_deref_type) { exp_styp := g.typ(expected_type) + got_styp := g.typ(got_type) got_idx := got_type.idx() - if got_type.is_ptr() { + got_sym := g.table.get_type_symbol(got_type) + if expected_is_ptr && got_is_ptr { + exp_der_styp := g.typ(expected_deref_type) + g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = ') + g.expr(expr) + g.write(', .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))') + } else if expected_is_ptr { + exp_der_styp := g.typ(expected_deref_type) + g.write('/* sum type cast */ ($exp_styp) memdup(&($exp_der_styp){.obj = memdup(&($got_styp[]) {') + g.expr(expr) + g.write('}, sizeof($got_styp)), .typ = $got_idx /* $got_sym.name */}, sizeof($exp_der_styp))') + } else if got_is_ptr { g.write('/* sum type cast */ ($exp_styp) {.obj = ') g.expr(expr) g.write(', .typ = $got_idx /* $got_sym.name */}') @@ -2287,7 +2301,9 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { sym := g.table.get_type_symbol(node.cond_type) // branch_sym := g.table.get_type_symbol(branch.typ) if sym.kind == .sum_type { - g.write('.typ == ') + dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' } + g.write(dot_or_ptr) + g.write('typ == ') } else if sym.kind == .interface_ { // g.write('._interface_idx == _${sym.name}_${branch_sym} ') g.write('._interface_idx == ') @@ -2338,7 +2354,9 @@ fn (mut g Gen) match_expr(node ast.MatchExpr) { // g.writeln('$it_type* it = ($it_type*)${tmp}.obj; // ST it') g.write('\t$it_type* it = ($it_type*)') g.expr(node.cond) - g.writeln('.obj; // ST it') + dot_or_ptr := if node.cond_type.is_ptr() { '->' } else { '.' } + g.write(dot_or_ptr) + g.writeln('obj; // ST it') if node.var_name.len > 0 { // for now we just copy it g.writeln('\t$it_type* $node.var_name = it;') diff --git a/vlib/v/gen/fn.v b/vlib/v/gen/fn.v index 6a0adb5592..0e4c8f380e 100644 --- a/vlib/v/gen/fn.v +++ b/vlib/v/gen/fn.v @@ -652,7 +652,9 @@ fn (mut g Gen) ref_or_deref_arg(arg ast.CallArg, expected_type table.Type) { } if !g.is_json_fn { arg_typ_sym := g.table.get_type_symbol(arg.typ) - if arg_typ_sym.kind != .function { + expected_deref_type := if expected_type.is_ptr() { expected_type.deref() } else { expected_type } + is_sum_type := g.table.get_type_symbol(expected_deref_type).kind == .sum_type + if !((arg_typ_sym.kind == .function) || is_sum_type) { g.write('(voidptr)&/*qq*/') } }