checker: detect and error on unreachable code in loops, after continue and break statements (#21294)

This commit is contained in:
Turiiya 2024-04-17 09:40:20 +02:00 committed by GitHub
parent 68bb0219c4
commit 16beb697ff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 9 deletions

View File

@ -2600,7 +2600,10 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
} }
} }
c.stmt(mut 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{ unreachable = token.Pos{
line_nr: -1 line_nr: -1
} }

View File

@ -1,7 +1,28 @@
vlib/v/checker/tests/unreachable_code.vv:3:4: error: unreachable code vlib/v/checker/tests/unreachable_code.vv:15:3: error: unreachable code
1 | fn foo() int { 13 | continue
2 | return if 1 == 1 { 1 } else { 2 } 14 | // ...
3 | a := 1 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) 29 | println(a)
5 | } 30 | }

View File

@ -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 } return if 1 == 1 { 1 } else { 2 }
a := 1 a := 1
println(a) println(a)
} }
fn main() { fn main() {
foo() foo(true)
} }