Skip to content

Commit 3ad384e

Browse files
authored
checker: cycle through all ast.ParExpr first in prefix_expr (fix #24584) (#24588)
1 parent dbc4071 commit 3ad384e

File tree

4 files changed

+48
-35
lines changed

4 files changed

+48
-35
lines changed

vlib/v/checker/checker.v

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4771,8 +4771,8 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
47714771
expr = expr.expr
47724772
}
47734773
if node.op == .amp {
4774-
if node.right is ast.Nil {
4775-
c.error('invalid operation: cannot take address of nil', node.right.pos())
4774+
if expr is ast.Nil {
4775+
c.error('invalid operation: cannot take address of nil', expr.pos())
47764776
}
47774777
if mut node.right is ast.PrefixExpr {
47784778
if node.right.op == .amp {
@@ -4782,76 +4782,78 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
47824782
if expr.op == .amp {
47834783
c.error('cannot take the address of this expression', expr.pos)
47844784
}
4785-
} else if mut node.right is ast.SelectorExpr {
4786-
if node.right.expr.is_literal() {
4787-
c.error('cannot take the address of a literal value', node.pos.extend(node.right.pos))
4788-
} else if node.right.expr is ast.StructInit {
4785+
} else if mut expr is ast.SelectorExpr {
4786+
if expr.expr.is_literal() {
4787+
c.error('cannot take the address of a literal value', node.pos.extend(expr.pos))
4788+
} else if expr.expr is ast.StructInit {
47894789
c.error('should not create object instance on the heap to simply access a member',
4790-
node.pos.extend(node.right.pos))
4790+
node.pos.extend(expr.pos))
47914791
}
47924792
right_sym := c.table.sym(right_type)
4793-
expr_sym := c.table.sym(node.right.expr_type)
4793+
expr_sym := c.table.sym(expr.expr_type)
47944794
if expr_sym.kind == .struct && (expr_sym.info as ast.Struct).is_minify
4795-
&& (node.right.typ == ast.bool_type_idx || (right_sym.kind == .enum
4795+
&& (expr.typ == ast.bool_type_idx || (right_sym.kind == .enum
47964796
&& !(right_sym.info as ast.Enum).is_flag
47974797
&& !(right_sym.info as ast.Enum).uses_exprs)) {
4798-
c.error('cannot take the address of field in struct `${c.table.type_to_str(node.right.expr_type)}`, which is tagged as `@[minify]`',
4799-
node.pos.extend(node.right.pos))
4798+
c.error('cannot take the address of field in struct `${c.table.type_to_str(expr.expr_type)}`, which is tagged as `@[minify]`',
4799+
node.pos.extend(expr.pos))
48004800
}
48014801

4802-
if node.right.typ.has_flag(.option) {
4803-
c.error('cannot take the address of an Option field', node.pos.extend(node.right.pos))
4802+
if expr.typ.has_flag(.option) {
4803+
c.error('cannot take the address of an Option field', node.pos.extend(expr.pos))
48044804
}
48054805
}
48064806
}
48074807
// TODO: testing ref/deref strategy
48084808
right_is_ptr := right_type.is_ptr()
4809-
if node.op == .amp && (!right_is_ptr || (right_is_ptr && node.right is ast.CallExpr)) {
4809+
if node.op == .amp && (!right_is_ptr || (right_is_ptr && expr is ast.CallExpr)) {
48104810
if expr in [ast.BoolLiteral, ast.CallExpr, ast.CharLiteral, ast.FloatLiteral, ast.IntegerLiteral,
48114811
ast.InfixExpr, ast.StringLiteral, ast.StringInterLiteral] {
48124812
c.error('cannot take the address of ${expr}', node.pos)
48134813
}
4814-
if mut node.right is ast.Ident {
4815-
if node.right.kind == .constant && !c.inside_unsafe && c.pref.experimental {
4816-
c.warn('cannot take the address of const outside `unsafe`', node.right.pos)
4814+
if mut expr is ast.Ident {
4815+
if expr.kind == .constant && !c.inside_unsafe && c.pref.experimental {
4816+
c.warn('cannot take the address of const outside `unsafe`', expr.pos)
48174817
}
48184818
}
4819-
if node.right is ast.SelectorExpr {
4819+
if expr is ast.SelectorExpr {
48204820
typ_sym := c.table.sym(right_type)
48214821
if typ_sym.kind == .map && !c.inside_unsafe {
48224822
c.error('cannot take the address of map values outside `unsafe`', node.pos)
48234823
}
48244824
}
4825-
if mut node.right is ast.IndexExpr {
4826-
typ_sym := c.table.sym(node.right.left_type)
4825+
if mut expr is ast.IndexExpr {
4826+
typ_sym := c.table.sym(expr.left_type)
48274827
mut is_mut := false
4828-
if mut node.right.left is ast.Ident {
4829-
ident := node.right.left
4828+
if mut expr.left is ast.Ident {
4829+
ident := expr.left
48304830
// TODO: temporary, remove this
48314831
ident_obj := ident.obj
48324832
if ident_obj is ast.Var {
48334833
is_mut = ident_obj.is_mut
48344834
}
48354835
}
4836-
if typ_sym.kind == .map {
4837-
c.error('cannot take the address of map values', node.right.pos)
4838-
}
48394836
if !c.inside_unsafe {
48404837
if typ_sym.kind == .array && is_mut {
48414838
c.error('cannot take the address of mutable array elements outside unsafe blocks',
4842-
node.right.pos)
4839+
expr.pos)
4840+
}
4841+
4842+
if typ_sym.kind == .map {
4843+
c.error('cannot take the address of map values outside `unsafe`',
4844+
expr.pos)
48434845
}
48444846
}
48454847
}
48464848
if !c.inside_fn_arg && !c.inside_unsafe {
4847-
c.mark_as_referenced(mut &node.right, false)
4849+
c.mark_as_referenced(mut &expr, false)
48484850
}
48494851
return right_type.ref()
4850-
} else if node.op == .amp && node.right !is ast.CastExpr {
4852+
} else if node.op == .amp && expr !is ast.CastExpr {
48514853
if !c.inside_fn_arg && !c.inside_unsafe {
4852-
c.mark_as_referenced(mut &node.right, false)
4854+
c.mark_as_referenced(mut &expr, false)
48534855
}
4854-
if node.right.is_auto_deref_var() {
4856+
if expr.is_auto_deref_var() {
48554857
return right_type
48564858
} else {
48574859
return right_type.ref()
@@ -4861,7 +4863,7 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
48614863
if node.op == .mul {
48624864
if right_type.has_flag(.option) {
48634865
c.error('type `?${right_sym.name}` is an Option, it must be unwrapped first; use `*var?` to do it',
4864-
node.right.pos())
4866+
expr.pos())
48654867
}
48664868
if right_type.is_ptr() {
48674869
return right_type.deref()
@@ -4874,11 +4876,11 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
48744876
if right_type.is_voidptr() {
48754877
c.error('cannot dereference to void', node.pos)
48764878
}
4877-
if mut node.right is ast.Ident {
4878-
if var := node.right.scope.find_var('${node.right.name}') {
4879+
if mut expr is ast.Ident {
4880+
if var := expr.scope.find_var('${expr.name}') {
48794881
if var.expr is ast.UnsafeExpr {
48804882
if var.expr.expr is ast.Nil {
4881-
c.error('cannot deference a `nil` pointer', node.right.pos)
4883+
c.error('cannot deference a `nil` pointer', expr.pos)
48824884
}
48834885
}
48844886
}

vlib/v/checker/tests/mut_map_get_value_address_err.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
vlib/v/checker/tests/mut_map_get_value_address_err.vv:5:9: error: cannot take the address of map values
1+
vlib/v/checker/tests/mut_map_get_value_address_err.vv:5:9: error: cannot take the address of map values outside `unsafe`
22
3 | 'key': 3
33
4 | }
44
5 | a := &m['key']

vlib/v/checker/tests/prefix_err.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,16 @@ vlib/v/checker/tests/prefix_err.vv:21:5: error: operator `~` can only be used wi
8888
21 | _ = ~true
8989
| ^
9090
22 | _ = !4
91+
23 |
9192
vlib/v/checker/tests/prefix_err.vv:22:5: error: operator `!` can only be used with bool types, but the value after `!` is of type `int literal` instead
9293
20 |
9394
21 | _ = ~true
9495
22 | _ = !4
9596
| ^
97+
23 |
98+
24 | mut arr := [12, 4]
99+
vlib/v/checker/tests/prefix_err.vv:25:11: error: cannot take the address of mutable array elements outside unsafe blocks
100+
23 |
101+
24 | mut arr := [12, 4]
102+
25 | _ := (&arr[1])
103+
| ~~~

vlib/v/checker/tests/prefix_err.vv

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ a <- 4
2020

2121
_ = ~true
2222
_ = !4
23+
24+
mut arr := [12, 4]
25+
_ := (&arr[1])

0 commit comments

Comments
 (0)