mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: add error for inc/dec for non lvalue (#17091)
This commit is contained in:
parent
5cd074a49e
commit
91799a1742
@ -3565,31 +3565,6 @@ pub fn (mut c Checker) is_comptime_var(node ast.Expr) bool {
|
|||||||
&& (node as ast.Ident).info is ast.IdentVar && (node as ast.Ident).kind == .variable && ((node as ast.Ident).obj as ast.Var).is_comptime_field
|
&& (node as ast.Ident).info is ast.IdentVar && (node as ast.Ident).kind == .variable && ((node as ast.Ident).obj as ast.Var).is_comptime_field
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type {
|
|
||||||
typ := c.unwrap_generic(c.expr(node.expr))
|
|
||||||
typ_sym := c.table.sym(typ)
|
|
||||||
is_non_void_pointer := (typ.is_ptr() || typ.is_pointer()) && typ_sym.kind != .voidptr
|
|
||||||
if !c.inside_unsafe && is_non_void_pointer && !node.expr.is_auto_deref_var() {
|
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
|
||||||
}
|
|
||||||
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
|
|
||||||
if c.inside_comptime_for_field {
|
|
||||||
if c.is_comptime_var(node.expr) {
|
|
||||||
return c.comptime_fields_default_type
|
|
||||||
} else if node.expr is ast.ComptimeSelector {
|
|
||||||
return c.comptime_fields_default_type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typ_str := c.table.type_to_str(typ)
|
|
||||||
c.error('invalid operation: ${node.op.str()} (non-numeric type `${typ_str}`)',
|
|
||||||
node.pos)
|
|
||||||
} else {
|
|
||||||
node.auto_locked, _ = c.fail_if_immutable(node.expr)
|
|
||||||
}
|
|
||||||
return typ
|
|
||||||
}
|
|
||||||
|
|
||||||
fn (mut c Checker) mark_as_referenced(mut node ast.Expr, as_interface bool) {
|
fn (mut c Checker) mark_as_referenced(mut node ast.Expr, as_interface bool) {
|
||||||
match mut node {
|
match mut node {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
|
41
vlib/v/checker/postfix.v
Normal file
41
vlib/v/checker/postfix.v
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
module checker
|
||||||
|
|
||||||
|
import v.ast
|
||||||
|
|
||||||
|
fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) ast.Type {
|
||||||
|
typ := c.unwrap_generic(c.expr(node.expr))
|
||||||
|
typ_sym := c.table.sym(typ)
|
||||||
|
is_non_void_pointer := (typ.is_ptr() || typ.is_pointer()) && typ_sym.kind != .voidptr
|
||||||
|
|
||||||
|
if node.op in [.inc, .dec] && !node.expr.is_lvalue() {
|
||||||
|
op_kind, bin_op_alt := if node.op == .inc {
|
||||||
|
'increment', '+'
|
||||||
|
} else {
|
||||||
|
'decrement', '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
c.add_error_detail('try rewrite this as `${node.expr} ${bin_op_alt} 1`')
|
||||||
|
c.error('cannot ${op_kind} `${node.expr}` because it is non lvalue expression',
|
||||||
|
node.expr.pos())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !c.inside_unsafe && is_non_void_pointer && !node.expr.is_auto_deref_var() {
|
||||||
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
||||||
|
}
|
||||||
|
if !(typ_sym.is_number() || ((c.inside_unsafe || c.pref.translated) && is_non_void_pointer)) {
|
||||||
|
if c.inside_comptime_for_field {
|
||||||
|
if c.is_comptime_var(node.expr) {
|
||||||
|
return c.comptime_fields_default_type
|
||||||
|
} else if node.expr is ast.ComptimeSelector {
|
||||||
|
return c.comptime_fields_default_type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typ_str := c.table.type_to_str(typ)
|
||||||
|
c.error('invalid operation: ${node.op.str()} (non-numeric type `${typ_str}`)',
|
||||||
|
node.pos)
|
||||||
|
} else {
|
||||||
|
node.auto_locked, _ = c.fail_if_immutable(node.expr)
|
||||||
|
}
|
||||||
|
return typ
|
||||||
|
}
|
6
vlib/v/checker/tests/inc_dec_fun_call.out
Normal file
6
vlib/v/checker/tests/inc_dec_fun_call.out
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
vlib/v/checker/tests/inc_dec_fun_call.vv:5:1: error: cannot decrement `foo()` because it is non lvalue expression
|
||||||
|
3 | }
|
||||||
|
4 |
|
||||||
|
5 | foo()--
|
||||||
|
| ~~~~~
|
||||||
|
Details: try rewrite this as `foo() - 1`
|
5
vlib/v/checker/tests/inc_dec_fun_call.vv
Normal file
5
vlib/v/checker/tests/inc_dec_fun_call.vv
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
fn foo() int {
|
||||||
|
return 100
|
||||||
|
}
|
||||||
|
|
||||||
|
foo()--
|
4
vlib/v/checker/tests/inc_num_literal.out
Normal file
4
vlib/v/checker/tests/inc_num_literal.out
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
vlib/v/checker/tests/inc_num_literal.vv:1:1: error: cannot increment `100` because it is non lvalue expression
|
||||||
|
1 | 100++
|
||||||
|
| ~~~
|
||||||
|
Details: try rewrite this as `100 + 1`
|
1
vlib/v/checker/tests/inc_num_literal.vv
Normal file
1
vlib/v/checker/tests/inc_num_literal.vv
Normal file
@ -0,0 +1 @@
|
|||||||
|
100++
|
0
vlib/v/checker/tests/inc_ok.out
Normal file
0
vlib/v/checker/tests/inc_ok.out
Normal file
6
vlib/v/checker/tests/inc_ok.vv
Normal file
6
vlib/v/checker/tests/inc_ok.vv
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mut mp := map[string]int{}
|
||||||
|
mut val := 100
|
||||||
|
|
||||||
|
(val)++
|
||||||
|
val++
|
||||||
|
mp["100"]++
|
4
vlib/v/checker/tests/inc_paren_expr.out
Normal file
4
vlib/v/checker/tests/inc_paren_expr.out
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
vlib/v/checker/tests/inc_paren_expr.vv:1:1: error: cannot increment `(100 * 10)` because it is non lvalue expression
|
||||||
|
1 | (100 * 10)++
|
||||||
|
| ~~~~~~~~~~
|
||||||
|
Details: try rewrite this as `(100 * 10) + 1`
|
1
vlib/v/checker/tests/inc_paren_expr.vv
Normal file
1
vlib/v/checker/tests/inc_paren_expr.vv
Normal file
@ -0,0 +1 @@
|
|||||||
|
(100 * 10)++
|
Loading…
Reference in New Issue
Block a user