mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: check labelled break/continue is inside a matching for
loop (#6910)
This commit is contained in:
parent
a1827d7f98
commit
51c737669d
@ -65,6 +65,7 @@ mut:
|
||||
vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path**
|
||||
vweb_gen_types []table.Type // vweb route checks
|
||||
prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type, stopping unwrapping then
|
||||
loop_label string // set when inside a labelled for loop
|
||||
}
|
||||
|
||||
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
||||
@ -2424,6 +2425,19 @@ fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral {
|
||||
return none
|
||||
}
|
||||
|
||||
[inline]
|
||||
fn (mut c Checker) check_loop_label(label string, pos token.Position) {
|
||||
if label.len == 0 {
|
||||
// ignore
|
||||
return
|
||||
}
|
||||
if c.loop_label.len != 0 {
|
||||
c.error('nesting of labelled `for` loops is not supported', pos)
|
||||
return
|
||||
}
|
||||
c.loop_label = label
|
||||
}
|
||||
|
||||
fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
$if trace_checker ? {
|
||||
stmt_pos := node.position()
|
||||
@ -2458,7 +2472,11 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
if c.in_for_count == 0 {
|
||||
c.error('$node.kind.str() statement not within a loop', node.pos)
|
||||
}
|
||||
// TODO: check any node.label is in scope for goto
|
||||
if node.label.len > 0 {
|
||||
if node.label != c.loop_label {
|
||||
c.error('invalid label name `$node.label`', node.pos)
|
||||
}
|
||||
}
|
||||
}
|
||||
ast.CompFor {
|
||||
// node.typ = c.expr(node.expr)
|
||||
@ -2490,7 +2508,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
c.stmt(node.init)
|
||||
c.expr(node.cond)
|
||||
c.stmt(node.inc)
|
||||
c.check_loop_label(node.label, node.pos)
|
||||
c.stmts(node.stmts)
|
||||
c.loop_label = ''
|
||||
c.in_for_count--
|
||||
}
|
||||
ast.ForInStmt {
|
||||
@ -2545,7 +2565,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
node.val_type = value_type
|
||||
scope.update_var_type(node.val_var, value_type)
|
||||
}
|
||||
c.check_loop_label(node.label, node.pos)
|
||||
c.stmts(node.stmts)
|
||||
c.loop_label = ''
|
||||
c.in_for_count--
|
||||
}
|
||||
ast.ForStmt {
|
||||
@ -2557,7 +2579,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||
}
|
||||
// TODO: update loop var type
|
||||
// how does this work currenly?
|
||||
c.check_loop_label(node.label, node.pos)
|
||||
c.stmts(node.stmts)
|
||||
c.loop_label = ''
|
||||
c.in_for_count--
|
||||
}
|
||||
ast.GlobalDecl {
|
||||
|
35
vlib/v/checker/tests/labelled_break_continue.out
Normal file
35
vlib/v/checker/tests/labelled_break_continue.out
Normal file
@ -0,0 +1,35 @@
|
||||
vlib/v/checker/tests/labelled_break_continue.vv:7:14: error: invalid label name `L2`
|
||||
5 | i++
|
||||
6 | for {
|
||||
7 | if i < 7 {continue L2}
|
||||
| ~~~~~~~~
|
||||
8 | else {break L2}
|
||||
9 | }
|
||||
vlib/v/checker/tests/labelled_break_continue.vv:8:10: error: invalid label name `L2`
|
||||
6 | for {
|
||||
7 | if i < 7 {continue L2}
|
||||
8 | else {break L2}
|
||||
| ~~~~~
|
||||
9 | }
|
||||
10 | }
|
||||
vlib/v/checker/tests/labelled_break_continue.vv:15:14: error: invalid label name `L1`
|
||||
13 | i = e
|
||||
14 | for {
|
||||
15 | if i < 3 {continue L1}
|
||||
| ~~~~~~~~
|
||||
16 | else {break L1}
|
||||
17 | }
|
||||
vlib/v/checker/tests/labelled_break_continue.vv:16:10: error: invalid label name `L1`
|
||||
14 | for {
|
||||
15 | if i < 3 {continue L1}
|
||||
16 | else {break L1}
|
||||
| ~~~~~
|
||||
17 | }
|
||||
18 | }
|
||||
vlib/v/checker/tests/labelled_break_continue.vv:21:11: error: nesting of labelled `for` loops is not supported
|
||||
19 | // check nested loops (not supported ATM)
|
||||
20 | L3: for ;; i++ {
|
||||
21 | L4: for {
|
||||
| ^
|
||||
22 | if i < 17 {continue L3}
|
||||
23 | else {break L3}
|
26
vlib/v/checker/tests/labelled_break_continue.vv
Normal file
26
vlib/v/checker/tests/labelled_break_continue.vv
Normal file
@ -0,0 +1,26 @@
|
||||
fn main() {
|
||||
mut i := 4
|
||||
// check branching to a later loop
|
||||
L1: for {
|
||||
i++
|
||||
for {
|
||||
if i < 7 {continue L2}
|
||||
else {break L2}
|
||||
}
|
||||
}
|
||||
// check branching to an earlier loop
|
||||
L2: for e in [1,2,3,4] {
|
||||
i = e
|
||||
for {
|
||||
if i < 3 {continue L1}
|
||||
else {break L1}
|
||||
}
|
||||
}
|
||||
// check nested loops (not supported ATM)
|
||||
L3: for ;; i++ {
|
||||
L4: for {
|
||||
if i < 17 {continue L3}
|
||||
else {break L3}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user