diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 0640e64367..8d86f2dc82 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -74,6 +74,7 @@ pub mut: inside_const bool inside_anon_fn bool inside_ref_lit bool + inside_defer bool inside_fn_arg bool // `a`, `b` in `a.f(b)` inside_ct_attr bool // true inside [if expr] skip_flags bool // should `#flag` and `#include` be skipped @@ -4486,7 +4487,9 @@ fn (mut c Checker) stmt(node ast.Stmt) { node.defer_vars[i] = id } } + c.inside_defer = true c.stmts(node.stmts) + c.inside_defer = false } ast.EnumDecl { c.enum_decl(node) @@ -4531,6 +4534,9 @@ fn (mut c Checker) stmt(node ast.Stmt) { } ast.GotoLabel {} ast.GotoStmt { + if c.inside_defer { + c.error('goto is not allowed in defer statements', node.pos) + } if !c.inside_unsafe { c.warn('`goto` requires `unsafe` (consider using labelled break/continue)', node.pos) @@ -4593,6 +4599,9 @@ fn (mut c Checker) block(node ast.Block) { } fn (mut c Checker) branch_stmt(node ast.BranchStmt) { + if c.inside_defer { + c.error('`$node.kind.str()` is not allowed in defer statements', node.pos) + } if c.in_for_count == 0 || c.inside_anon_fn { c.error('$node.kind.str() statement not within a loop', node.pos) } diff --git a/vlib/v/checker/tests/defer_in_for.out b/vlib/v/checker/tests/defer_in_for.out new file mode 100644 index 0000000000..59faded16b --- /dev/null +++ b/vlib/v/checker/tests/defer_in_for.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/defer_in_for.vv:4:13: error: `break` is not allowed in defer statements + 2 | for true { + 3 | defer { + 4 | break + | ~~~~~ + 5 | } + 6 | } \ No newline at end of file diff --git a/vlib/v/checker/tests/defer_in_for.vv b/vlib/v/checker/tests/defer_in_for.vv new file mode 100644 index 0000000000..bb2525fe2c --- /dev/null +++ b/vlib/v/checker/tests/defer_in_for.vv @@ -0,0 +1,7 @@ +fn main() { + for true { + defer { + break + } + } +} \ No newline at end of file