medvednikov

/

vxx2Public
0 commits0 issues4 pull requests0 contributorsDiscussionsProjectsCI

fix(cgen): fix address-of and as_cast pointer codegen #6

Openguweigangwants to mergepr/27481intomaster· last Jun 17
2 files changed+51-7
vlib/v/gen/c/cgen.v+43-7

@@ -104,6 +104,7 @@ mut:

104104 is_void_expr_stmt bool // ExprStmt whose result is discarded

105105 is_arraymap_set bool // map or array set value state

106106 is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&u8(unsafe { nil })` etc

107+ is_direct_amp_as_cast bool // direct `&(expr as Type)` operand; consumed by AsCast codegen

107108 is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)

108109 is_shared bool // for initialization of hidden mutex in `[rw]shared` literals

109110 is_vlines_enabled bool // is it safe to generate #line directives when -g is passed

@@ -6518,12 +6519,24 @@ fn (mut g Gen) expr(node_ ast.Expr) {

65186519 // where the receiver is already a pointer in C), the `&` and the

65196520 // implicit dereference cancel out, so emit neither.

65206521 is_amp_auto_deref := node.op == .amp && node.right.is_auto_deref_var()

6522+ mut is_as_cast_ptr := false

65216523 if !g.is_option_auto_heap {

65226524 has_slice_call = node.op == .amp && node.right is ast.IndexExpr

65236525 && node.right.index is ast.RangeExpr

6526+ if node.op == .amp && tmp_var == '' {

6527+ mut right_expr := node.right

6528+ if right_expr is ast.ParExpr {

6529+ right_expr = right_expr.expr

6530+ }

6531+ if right_expr is ast.AsCast {

6532+ if g.as_cast_will_use_ptr(right_expr) {

6533+ is_as_cast_ptr = true

6534+ }

6535+ }

6536+ }

65246537 if has_slice_call {

65256538 g.write('ADDR(${g.styp(node.right_type)}, ')

6526- } else if !is_amp_auto_deref {

6539+ } else if !is_amp_auto_deref && !is_as_cast_ptr {

65276540 g.write(node.op.str())

65286541 }

65296542 }

@@ -6552,7 +6565,10 @@ fn (mut g Gen) expr(node_ ast.Expr) {

65526565 g.write('(')

65536566 }

65546567 if tmp_var == '' {

6568+ old_is_direct_amp_as_cast := g.is_direct_amp_as_cast

6569+ g.is_direct_amp_as_cast = is_as_cast_ptr

65556570 g.expr(node.right)

6571+ g.is_direct_amp_as_cast = old_is_direct_amp_as_cast

65566572 } else {

65576573 g.write(tmp_var)

65586574 }

@@ -12838,10 +12854,10 @@ fn (mut g Gen) as_cast_option_payload_expr_from_expr(typ ast.Type, expr ast.Expr

1283812854 return g.as_cast_option_payload_expr(typ, g.expr_string(expr), false)

1283912855}

1284012856

12841-fn (mut g Gen) write_as_cast_call_start(styp string, sym ast.TypeSymbol) {

12857+fn (mut g Gen) write_as_cast_call_start(styp string, sym ast.TypeSymbol, is_direct_amp bool) {

1284212858 if sym.info is ast.FnType {

1284312859 g.write('(${styp})')

12844- } else if g.inside_smartcast {

12860+ } else if g.inside_smartcast || is_direct_amp {

1284512861 g.write('(${styp}*)')

1284612862 } else {

1284712863 g.write('*(${styp}*)')

@@ -12909,7 +12925,27 @@ fn as_cast_operand_needs_tmp_eval(expr ast.Expr) bool {

1290912925 }

1291012926}

1291112927

12928+fn (mut g Gen) as_cast_will_use_ptr(node ast.AsCast) bool {

12929+ unwrapped_node_typ := g.unwrap_generic(node.typ)

12930+ unwrapped_expr_type := g.unwrap_generic(node.expr_type)

12931+ expr_type_without_option := unwrapped_expr_type.clear_flag(.option)

12932+ expr_type_sym := g.table.sym(unwrapped_expr_type)

12933+ if expr_type_sym.kind == .sum_type && expr_type_without_option == unwrapped_node_typ {

12934+ return false

12935+ }

12936+ if expr_type_sym.info is ast.SumType

12937+ || (expr_type_sym.info is ast.Interface && node.expr_type != node.typ) {

12938+ return true

12939+ }

12940+ return false

12941+}

12942+

1291212943fn (mut g Gen) as_cast(node ast.AsCast) {

12944+ is_direct_amp := g.is_direct_amp_as_cast

12945+ g.is_direct_amp_as_cast = false

12946+ defer {

12947+ g.is_direct_amp_as_cast = is_direct_amp

12948+ }

1291312949 // Make sure the sum type can be cast to this type (the types

1291412950 // are the same), otherwise panic.

1291512951 unwrapped_node_typ := g.unwrap_generic(node.typ)

@@ -12980,7 +13016,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {

1298013016 }

1298113017 obj_expr := '(${expr_str})${dot}_${payload_sym.cname}'

1298213018 tag_expr := '(${expr_str})${dot}_typ'

12983- g.write_as_cast_call_start(styp, sym)

13019+ g.write_as_cast_call_start(styp, sym, is_direct_amp)

1298413020 g.write_as_cast_call(obj_expr, tag_expr, sidx, index_exprs)

1298513021 if !g.is_cc_msvc {

1298613022 g.write('; })')

@@ -12993,7 +13029,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {

1299313029 }

1299413030 obj_expr := '(${expr_str})${dot}_${payload_sym.cname}'

1299513031 tag_expr := '(${expr_str})${dot}_typ'

12996- g.write_as_cast_call_start(styp, sym)

13032+ g.write_as_cast_call_start(styp, sym, is_direct_amp)

1299713033 g.write_as_cast_call(obj_expr, tag_expr, sidx, index_exprs)

1299813034 }

1299913035

@@ -13069,7 +13105,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {

1306913105 }

1307013106 obj_expr := '${tmp_var}${dot}_${payload_sym.cname}'

1307113107 tag_expr := 'v_typeof_interface_idx_${expr_type_sym.cname}(${tmp_var}${dot}_typ)'

13072- g.write_as_cast_call_start(styp, sym)

13108+ g.write_as_cast_call_start(styp, sym, is_direct_amp)

1307313109 g.write_as_cast_call(obj_expr, tag_expr, sidx, index_exprs)

1307413110 if !g.is_cc_msvc {

1307513111 g.write('; })')

@@ -13078,7 +13114,7 @@ fn (mut g Gen) as_cast(node ast.AsCast) {

1307813114 expr_str := g.expr_string(node.expr)

1307913115 obj_expr := '(${expr_str})${dot}_${payload_sym.cname}'

1308013116 tag_expr := 'v_typeof_interface_idx_${expr_type_sym.cname}((${expr_str})${dot}_typ)'

13081- g.write_as_cast_call_start(styp, sym)

13117+ g.write_as_cast_call_start(styp, sym, is_direct_amp)

1308213118 g.write_as_cast_call(obj_expr, tag_expr, sidx, index_exprs)

1308313119 }

1308413120

vlib/v/tests/casts/cast_with_call_in_address_test.v+8-0

@@ -15,6 +15,8 @@ mut:

1515 val int

1616}

1717

18+type FooBarSum = Bar | Foo

19+

1820fn test_main() {

1921 mut fbs := []&FooBar{}

2022 fbs << &Foo{1}

@@ -22,6 +24,12 @@ fn test_main() {

2224 println(a)

2325 b := &(fbs.last() as Foo)

2426 println(b)

27+ fb := fbs[0]

28+ field_ptr := &((fb as Foo).val)

29+ assert *field_ptr == 1

30+ sum := FooBarSum(Foo{2})

31+ sum_field_ptr := &((sum as Foo).val)

32+ assert *sum_field_ptr == 2

2533 arr1 := [(fbs.last() as Foo)]

2634 arr2 := [&(fbs.last() as Foo)]

2735 arr3 := [&(get_foo_bar() as Foo)]