Skip to content

Commit

Permalink
checker: detect and error on unreachable code in loops, after `contin…
Browse files Browse the repository at this point in the history
…ue` and `break` statements (#21294)
  • Loading branch information
ttytm committed Apr 17, 2024
1 parent 68bb021 commit 16beb69
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 9 deletions.
5 changes: 4 additions & 1 deletion vlib/v/checker/checker.v
Expand Up @@ -2600,7 +2600,10 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
}
}
c.stmt(mut stmt)
if stmt is ast.GotoLabel {
if !c.inside_anon_fn && c.in_for_count > 0 && stmt is ast.BranchStmt
&& stmt.kind in [.key_continue, .key_break] {
c.scope_returns = true
} else if stmt is ast.GotoLabel {
unreachable = token.Pos{
line_nr: -1
}
Expand Down
33 changes: 27 additions & 6 deletions vlib/v/checker/tests/unreachable_code.out
@@ -1,7 +1,28 @@
vlib/v/checker/tests/unreachable_code.vv:3:4: error: unreachable code
1 | fn foo() int {
2 | return if 1 == 1 { 1 } else { 2 }
3 | a := 1
vlib/v/checker/tests/unreachable_code.vv:15:3: error: unreachable code
13 | continue
14 | // ...
15 | eprintln('continue')
| ~~~~~~~~~~~~~~~~~~~~
16 | }
17 | for _ in 0 .. 3 {
vlib/v/checker/tests/unreachable_code.vv:21:4: error: unreachable code
19 | break
20 | // ...
21 | eprintln('done')
| ~~~~~~~~~~~~~~~~
22 | }
23 | break
vlib/v/checker/tests/unreachable_code.vv:25:3: error: unreachable code
23 | break
24 | // ...
25 | return 3
| ~~~~~~~~
26 | }
27 | return if 1 == 1 { 1 } else { 2 }
vlib/v/checker/tests/unreachable_code.vv:28:4: error: unreachable code
26 | }
27 | return if 1 == 1 { 1 } else { 2 }
28 | a := 1
| ~~
4 | println(a)
5 | }
29 | println(a)
30 | }
30 changes: 28 additions & 2 deletions vlib/v/checker/tests/unreachable_code.vv
@@ -1,8 +1,34 @@
fn foo() int {
fn foo(condition bool) int {
for _ in 0 .. 1 {
if condition {
continue // scope should not cause errors.
}
if !condition {
break
}
eprintln('done')
break
}
for _ in 0 .. 2 {
continue
// ...
eprintln('continue')
}
for _ in 0 .. 3 {
if condition {
break
// ...
eprintln('done')
}
break
// ...
return 3
}
return if 1 == 1 { 1 } else { 2 }
a := 1
println(a)
}

fn main() {
foo()
foo(true)
}

0 comments on commit 16beb69

Please sign in to comment.