1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser: disallow statements after a return, branch check $if, $else, switch, and loops correctly

This commit is contained in:
Julian Schurhammer
2019-08-10 20:26:42 +12:00
committed by Alexander Medvednikov
parent 58b52aa9fb
commit 1864e92ff4
26 changed files with 97 additions and 94 deletions

View File

@ -102,7 +102,6 @@ fn platform_postfix_to_ifdefguard(name string) string {
case '_mac.v': return '#ifdef __APPLE__'
}
panic('bad platform_postfix "$name"')
return ''
}
fn (v mut V) new_parser(path string, pass Pass) Parser {
@ -296,7 +295,6 @@ fn (p mut Parser) parse() {
if false && !p.first_pass() && p.fileis('main.v') {
out := os.create('/var/tmp/fmt.v') or {
panic('failed to create fmt.v')
return
}
out.writeln(p.scanner.fmt_out.str())
out.close()
@ -1103,6 +1101,9 @@ fn (p mut Parser) vh_genln(s string) {
}
fn (p mut Parser) statement(add_semi bool) string {
if(p.returns) {
p.error('unreachable code')
}
p.cgen.is_tmp = false
tok := p.tok
mut q := ''
@ -1321,6 +1322,7 @@ fn (p mut Parser) var_decl() {
if !p.returns && p.prev_tok2 != .key_continue && p.prev_tok2 != .key_break {
p.error('`or` block must return/continue/break/panic')
}
p.returns = false
}
p.register_var(Var {
name: name
@ -1983,7 +1985,6 @@ fn (p mut Parser) index_expr(typ_ string, fn_ph int) string {
p.cgen.insert_before('$typ $tmp = $tmp_val;')
}
return typ
return 'void'
}
// else if p.pref.is_verbose && p.assigned_var != '' {
// p.error('didnt assign')
@ -2905,7 +2906,6 @@ fn os_name_to_ifdef(name string) string {
case 'msvc': return '_MSC_VER'
}
panic('bad os ifdef name "$name"')
return ''
}
fn (p mut Parser) if_st(is_expr bool, elif_depth int) string {
@ -3167,6 +3167,7 @@ fn (p mut Parser) for_st() {
p.statements()
p.close_scope()
p.for_expr_cnt--
p.returns = false // TODO handle loops that are guaranteed to return
}
fn (p mut Parser) switch_statement() {
@ -3180,7 +3181,9 @@ fn (p mut Parser) switch_statement() {
expr := p.cgen.end_tmp()
p.check(.lcbr)
mut i := 0
mut all_cases_return := true
for p.tok == .key_case || p.tok == .key_default || p.peek() == .arrow || p.tok == .key_else {
p.returns = false
if p.tok == .key_default || p.tok == .key_else {
p.genln('else { // default:')
if p.tok == .key_default {
@ -3191,7 +3194,8 @@ fn (p mut Parser) switch_statement() {
p.check(.arrow)
}
p.statements()
break
p.returns = all_cases_return && p.returns
return
}
if i > 0 {
p.gen('else ')
@ -3228,8 +3232,10 @@ fn (p mut Parser) switch_statement() {
p.gen(')) {')
p.genln('/* case */')
p.statements()
all_cases_return = all_cases_return && p.returns
i++
}
p.returns = false // only get here when no default, so return is not guaranteed
}
fn (p mut Parser) assert_statement() {