checker: make sure functions return
parent
581d836de6
commit
449d839684
|
@ -32,6 +32,7 @@ mut:
|
||||||
in_for_count int // if checker is currently in an for loop
|
in_for_count int // if checker is currently in an for loop
|
||||||
// checked_ident string // to avoid infinit checker loops
|
// checked_ident string // to avoid infinit checker loops
|
||||||
var_decl_name string
|
var_decl_name string
|
||||||
|
returns bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
||||||
|
@ -250,6 +251,9 @@ fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||||
|
if call_expr.name == 'panic' {
|
||||||
|
c.returns = true
|
||||||
|
}
|
||||||
c.stmts(call_expr.or_block.stmts)
|
c.stmts(call_expr.or_block.stmts)
|
||||||
if call_expr.is_method {
|
if call_expr.is_method {
|
||||||
left_type := c.expr(call_expr.left)
|
left_type := c.expr(call_expr.left)
|
||||||
|
@ -876,6 +880,11 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
c.expected_type = table.void_type
|
c.expected_type = table.void_type
|
||||||
c.fn_return_type = it.return_type
|
c.fn_return_type = it.return_type
|
||||||
c.stmts(it.stmts)
|
c.stmts(it.stmts)
|
||||||
|
if !it.is_c && !it.no_body && it.return_type != table.void_type && !c.returns &&
|
||||||
|
!(it.name in ['panic', 'exit']) {
|
||||||
|
c.error('missing return at end of function `$it.name`', it.pos)
|
||||||
|
}
|
||||||
|
c.returns = false
|
||||||
}
|
}
|
||||||
ast.ForStmt {
|
ast.ForStmt {
|
||||||
c.in_for_count++
|
c.in_for_count++
|
||||||
|
@ -937,6 +946,7 @@ fn (c mut Checker) stmt(node ast.Stmt) {
|
||||||
ast.Import {}
|
ast.Import {}
|
||||||
// ast.GlobalDecl {}
|
// ast.GlobalDecl {}
|
||||||
ast.Return {
|
ast.Return {
|
||||||
|
c.returns = true
|
||||||
c.return_stmt(mut it)
|
c.return_stmt(mut it)
|
||||||
}
|
}
|
||||||
// ast.StructDecl {}
|
// ast.StructDecl {}
|
||||||
|
|
|
@ -83,6 +83,7 @@ pub fn (p mut Parser) call_args() []ast.CallArg {
|
||||||
|
|
||||||
fn (p mut Parser) fn_decl() ast.FnDecl {
|
fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
// p.table.clear_vars()
|
// p.table.clear_vars()
|
||||||
|
pos := p.tok.position()
|
||||||
p.open_scope()
|
p.open_scope()
|
||||||
is_deprecated := p.attr == 'deprecated'
|
is_deprecated := p.attr == 'deprecated'
|
||||||
is_pub := p.tok.kind == .key_pub
|
is_pub := p.tok.kind == .key_pub
|
||||||
|
@ -207,7 +208,7 @@ fn (p mut Parser) fn_decl() ast.FnDecl {
|
||||||
rec_mut: rec_mut
|
rec_mut: rec_mut
|
||||||
is_c: is_c
|
is_c: is_c
|
||||||
no_body: no_body
|
no_body: no_body
|
||||||
pos: p.tok.position()
|
pos: pos
|
||||||
is_builtin: p.builtin_mod || p.mod in ['math', 'strconv', 'strconv.ftoa', 'hash.wyhash',
|
is_builtin: p.builtin_mod || p.mod in ['math', 'strconv', 'strconv.ftoa', 'hash.wyhash',
|
||||||
'math.bits', 'strings']
|
'math.bits', 'strings']
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue