From c500044baeb381392433a0fc9410ef5a483db7cc Mon Sep 17 00:00:00 2001 From: Henrixounez <30901439+Henrixounez@users.noreply.github.com> Date: Wed, 29 Apr 2020 12:31:18 +0200 Subject: [PATCH] checker: unreachable code warning --- vlib/v/ast/ast.v | 76 +++++++++++++++++++++++ vlib/v/checker/checker.v | 12 ++++ vlib/v/checker/tests/unreachable_code.out | 7 +++ vlib/v/checker/tests/unreachable_code.vv | 8 +++ 4 files changed, 103 insertions(+) create mode 100644 vlib/v/checker/tests/unreachable_code.out create mode 100644 vlib/v/checker/tests/unreachable_code.vv diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index cd15891035..bdc434ac24 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -852,3 +852,79 @@ fn (expr Expr) position() token.Position { } } } + +fn (stmt Stmt) position() token.Position { + match mut stmt { + AssertStmt { + return it.pos + } + AssignStmt { + return it.pos + } + // Attr { + // } + // Block { + // } + // BranchStmt { + // } + Comment { + return it.pos + } + CompIf { + return it.pos + } + ConstDecl { + return it.pos + } + // DeferStmt { + // } + EnumDecl { + return it.pos + } + ExprStmt { + return it.pos + } + FnDecl { + return it.pos + } + ForCStmt { + return it.pos + } + ForInStmt { + return it.pos + } + ForStmt { + return it.pos + } + // GlobalDecl { + // } + // GoStmt { + // } + // GotoLabel { + // } + // GotoStmt { + // } + // HashStmt { + // } + Import { + return it.pos + } + // InterfaceDecl { + // } + // Module { + // } + Return { + return it.pos + } + StructDecl { + return it.pos + } + // TypeDecl { + // } + // UnsafeStmt { + // } + else { + return token.Position{} + } + } +} diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index d87181a60f..839db6917f 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -34,6 +34,7 @@ mut: // checked_ident string // to avoid infinit checker loops var_decl_name string returns bool + scope_returns bool mod string // current module name is_builtin_mod bool // are we in `builtin`? } @@ -1398,6 +1399,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { ast.Return { c.returns = true c.return_stmt(mut it) + c.scope_returns = true } ast.StructDecl { c.struct_decl(it) @@ -1416,10 +1418,20 @@ fn (mut c Checker) stmt(node ast.Stmt) { } fn (mut c Checker) stmts(stmts []ast.Stmt) { + mut unreachable := token.Position{line_nr: -1} c.expected_type = table.void_type for stmt in stmts { + if c.scope_returns { + if unreachable.line_nr == -1 { + unreachable = stmt.position() + } + } c.stmt(stmt) } + if unreachable.line_nr >= 0 { + c.warn('unreachable code', unreachable) + } + c.scope_returns = false c.expected_type = table.void_type } diff --git a/vlib/v/checker/tests/unreachable_code.out b/vlib/v/checker/tests/unreachable_code.out new file mode 100644 index 0000000000..b78ee492d9 --- /dev/null +++ b/vlib/v/checker/tests/unreachable_code.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/unreachable_code.v:3:7: error: unreachable code + 1| fn foo() int { + 2| return if 1 == 1 { 1 } else { 2 } + 3| a := 1 + ^ + 4| println(a) + 5| } diff --git a/vlib/v/checker/tests/unreachable_code.vv b/vlib/v/checker/tests/unreachable_code.vv new file mode 100644 index 0000000000..7da480f8aa --- /dev/null +++ b/vlib/v/checker/tests/unreachable_code.vv @@ -0,0 +1,8 @@ +fn foo() int { + return if 1 == 1 { 1 } else { 2 } + a := 1 + println(a) +} +fn main() { + foo() +}