From 3af35eef14a896eaf855cad1c24785038bdd9b63 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 10 Oct 2024 14:52:24 -0300 Subject: [PATCH] checker: fix missing check for empty noreturn fn (fix #22468) (#22474) --- vlib/v/checker/return.v | 11 +++++++---- vlib/v/checker/tests/empty_fn_noreturn_err.out | 5 +++++ vlib/v/checker/tests/empty_fn_noreturn_err.vv | 3 +++ vlib/v/tests/reflection_test.v | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 vlib/v/checker/tests/empty_fn_noreturn_err.out create mode 100644 vlib/v/checker/tests/empty_fn_noreturn_err.vv diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 57eb9ac9b2..2d5aead307 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -367,8 +367,9 @@ fn (mut c Checker) check_noreturn_fn_decl(mut node ast.FnDecl) { if uses_return_stmt(node.stmts) { c.error('[noreturn] functions cannot use return statements', node.pos) } + mut pos := node.pos + mut is_valid_end_of_noreturn_fn := false if node.stmts.len != 0 { - mut is_valid_end_of_noreturn_fn := false last_stmt := node.stmts.last() match last_stmt { ast.ExprStmt { @@ -391,11 +392,13 @@ fn (mut c Checker) check_noreturn_fn_decl(mut node ast.FnDecl) { else {} } if !is_valid_end_of_noreturn_fn { - c.error('@[noreturn] functions should end with a call to another @[noreturn] function, or with an infinite `for {}` loop', - last_stmt.pos) - return + pos = last_stmt.pos } } + if !is_valid_end_of_noreturn_fn { + c.error('@[noreturn] functions should end with a call to another @[noreturn] function, or with an infinite `for {}` loop', + pos) + } } fn uses_return_stmt(stmts []ast.Stmt) bool { diff --git a/vlib/v/checker/tests/empty_fn_noreturn_err.out b/vlib/v/checker/tests/empty_fn_noreturn_err.out new file mode 100644 index 0000000000..f9ddb0bfce --- /dev/null +++ b/vlib/v/checker/tests/empty_fn_noreturn_err.out @@ -0,0 +1,5 @@ +vlib/v/checker/tests/empty_fn_noreturn_err.vv:2:1: error: @[noreturn] functions should end with a call to another @[noreturn] function, or with an infinite `for {}` loop + 1 | @[noreturn] + 2 | fn f() { + | ~~~~~~ + 3 | } diff --git a/vlib/v/checker/tests/empty_fn_noreturn_err.vv b/vlib/v/checker/tests/empty_fn_noreturn_err.vv new file mode 100644 index 0000000000..486d5541bc --- /dev/null +++ b/vlib/v/checker/tests/empty_fn_noreturn_err.vv @@ -0,0 +1,3 @@ +@[noreturn] +fn f() { +} diff --git a/vlib/v/tests/reflection_test.v b/vlib/v/tests/reflection_test.v index 47b0c6e01d..fb4c63a858 100644 --- a/vlib/v/tests/reflection_test.v +++ b/vlib/v/tests/reflection_test.v @@ -21,6 +21,7 @@ fn test2(arg []string) {} @[noreturn] fn test3(a reflection.Function) { + panic('foo') } fn test_module_existing() {