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
|
||||
}
|
||||
|
||||
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) {
|
||||
match mut node {
|
||||
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