| 1 | module checker |
| 2 | |
| 3 | import v.ast |
| 4 | |
| 5 | fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type { |
| 6 | typ := c.unwrap_generic(c.type_resolver.get_type_or_default(node, c.expr(mut node.expr))) |
| 7 | typ_sym := c.table.sym(typ) |
| 8 | is_non_void_pointer := typ.is_any_kind_of_pointer() && !typ.has_flag(.shared_f) |
| 9 | && typ_sym.kind != .voidptr |
| 10 | mut unwrapped_question_type := c.unwrap_generic(c.type_resolver.get_type(node.expr)) |
| 11 | if unwrapped_question_type != 0 && c.table.sym(unwrapped_question_type).kind == .alias { |
| 12 | unaliased_question_type := c.table.unaliased_type(unwrapped_question_type) |
| 13 | if unaliased_question_type.has_option_or_result() { |
| 14 | unwrapped_question_type = c.unwrap_generic(unaliased_question_type) |
| 15 | } |
| 16 | } |
| 17 | unwrapped_question_type = unwrapped_question_type.clear_option_and_result() |
| 18 | |
| 19 | if node.op in [.inc, .dec] && !node.expr.is_lvalue() { |
| 20 | op_kind, bin_op_alt := if node.op == .inc { 'increment', '+' } else { 'decrement', '-' } |
| 21 | c.add_error_detail('try rewrite this as `${node.expr} ${bin_op_alt} 1`') |
| 22 | c.error('cannot ${op_kind} `${node.expr}` because it is non lvalue expression', |
| 23 | node.expr.pos()) |
| 24 | } |
| 25 | if node.op != .question && !c.inside_unsafe && is_non_void_pointer |
| 26 | && !node.expr.is_auto_deref_var() { |
| 27 | if !c.pref.translated && !c.file.is_translated { |
| 28 | c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos) |
| 29 | } |
| 30 | } |
| 31 | if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) { |
| 32 | if c.comptime.comptime_for_field_var != '' { |
| 33 | if c.comptime.is_comptime(node.expr) || node.expr is ast.ComptimeSelector { |
| 34 | node.typ = if node.op == .question { |
| 35 | unwrapped_question_type |
| 36 | } else { |
| 37 | c.unwrap_generic(c.type_resolver.get_type(node.expr)) |
| 38 | } |
| 39 | return node.typ |
| 40 | } |
| 41 | } |
| 42 | if node.op != .question { |
| 43 | typ_str := c.table.type_to_str(typ) |
| 44 | c.error('invalid operation: ${node.op.str()} (non-numeric type `${typ_str}`)', node.pos) |
| 45 | } else { |
| 46 | node.typ = unwrapped_question_type |
| 47 | return node.typ |
| 48 | } |
| 49 | } else { |
| 50 | if node.op != .question { |
| 51 | node.auto_locked, _ = c.fail_if_immutable(mut node.expr) |
| 52 | } else { |
| 53 | node.typ = unwrapped_question_type |
| 54 | return node.typ |
| 55 | } |
| 56 | } |
| 57 | node.typ = typ |
| 58 | return typ |
| 59 | } |
| 60 | |