checker: `[noreturn]` part 2 (cleanup) (#10667)
parent
da9c75f2ca
commit
972542d6ee
|
@ -480,6 +480,7 @@ fn (t Tree) fn_decl(node ast.FnDecl) &Node {
|
|||
obj.add('is_pub', t.bool_node(node.is_pub))
|
||||
obj.add('is_variadic', t.bool_node(node.is_variadic))
|
||||
obj.add('is_anon', t.bool_node(node.is_anon))
|
||||
obj.add('is_noreturn', t.bool_node(node.is_noreturn))
|
||||
obj.add('is_manualfree', t.bool_node(node.is_manualfree))
|
||||
obj.add('is_main', t.bool_node(node.is_main))
|
||||
obj.add('is_test', t.bool_node(node.is_test))
|
||||
|
@ -1393,22 +1394,24 @@ fn (t Tree) ident_fn(node ast.IdentFn) &Node {
|
|||
fn (t Tree) call_expr(node ast.CallExpr) &Node {
|
||||
mut obj := new_object()
|
||||
obj.add('ast_type', t.string_node('CallExpr'))
|
||||
obj.add('left', t.expr(node.left))
|
||||
obj.add('is_method', t.bool_node(node.is_method))
|
||||
obj.add('mod', t.string_node(node.mod))
|
||||
obj.add('name', t.string_node(node.name))
|
||||
obj.add('language', t.enum_node(node.language))
|
||||
obj.add('left_type', t.type_node(node.left_type))
|
||||
obj.add('receiver_type', t.type_node(node.receiver_type))
|
||||
obj.add('return_type', t.type_node(node.return_type))
|
||||
obj.add('left', t.expr(node.left))
|
||||
obj.add('is_method', t.bool_node(node.is_method))
|
||||
obj.add('is_keep_alive', t.bool_node(node.is_keep_alive))
|
||||
obj.add('is_noreturn', t.bool_node(node.is_noreturn))
|
||||
obj.add('should_be_skipped', t.bool_node(node.should_be_skipped))
|
||||
obj.add('free_receiver', t.bool_node(node.free_receiver))
|
||||
obj.add('scope', t.number_node(int(node.scope)))
|
||||
obj.add('args', t.array_node_call_arg(node.args))
|
||||
obj.add('expected_arg_types', t.array_node_type(node.expected_arg_types))
|
||||
obj.add('concrete_types', t.array_node_type(node.concrete_types))
|
||||
obj.add('or_block', t.or_expr(node.or_block))
|
||||
obj.add('left_type', t.type_node(node.left_type))
|
||||
obj.add('receiver_type', t.type_node(node.receiver_type))
|
||||
obj.add('return_type', t.type_node(node.return_type))
|
||||
obj.add('should_be_skipped', t.bool_node(node.should_be_skipped))
|
||||
obj.add('concrete_list_pos', t.position(node.concrete_list_pos))
|
||||
obj.add('free_receiver', t.bool_node(node.free_receiver))
|
||||
obj.add('from_embed_type', t.type_node(node.from_embed_type))
|
||||
obj.add('comments', t.array_node_comment(node.comments))
|
||||
obj.add('pos', t.position(node.pos))
|
||||
|
|
|
@ -332,6 +332,7 @@ fn get_compile_name_of_potential_v_project(file string) string {
|
|||
return pfolder
|
||||
}
|
||||
|
||||
[noreturn]
|
||||
fn verror(s string) {
|
||||
util.verror('vfmt error', s)
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ fn vhalt() {
|
|||
[noreturn]
|
||||
pub fn exit(code int) {
|
||||
C.exit(code)
|
||||
vhalt()
|
||||
}
|
||||
|
||||
fn vcommithash() string {
|
||||
|
|
|
@ -16,7 +16,7 @@ fn C.realloc(a &byte, b int) &byte
|
|||
|
||||
fn C.free(ptr voidptr)
|
||||
|
||||
[trusted]
|
||||
[noreturn; trusted]
|
||||
fn C.exit(code int)
|
||||
|
||||
fn C.qsort(base voidptr, items size_t, item_size size_t, cb qsort_callback_func)
|
||||
|
|
|
@ -343,12 +343,12 @@ fn test_realpath_does_not_absolutize_non_existing_relative_paths() {
|
|||
}
|
||||
}
|
||||
|
||||
fn test_realpath_absolutepath_symlink() {
|
||||
fn test_realpath_absolutepath_symlink() ? {
|
||||
file_name := 'tolink_file.txt'
|
||||
symlink_name := 'symlink.txt'
|
||||
mut f := os.create(file_name) or { panic(err) }
|
||||
mut f := os.create(file_name) ?
|
||||
f.close()
|
||||
assert os.symlink(file_name, symlink_name) or { panic(err) }
|
||||
assert os.symlink(file_name, symlink_name) ?
|
||||
rpath := os.real_path(symlink_name)
|
||||
println(rpath)
|
||||
assert os.is_abs_path(rpath)
|
||||
|
|
|
@ -461,6 +461,7 @@ fn error_with_pos(s string, fpath string, pos token.Position) {
|
|||
exit(1)
|
||||
}
|
||||
|
||||
[noreturn]
|
||||
fn verror(s string) {
|
||||
util.verror('builder error', s)
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@ pub fn compile(command string, pref &pref.Preferences) {
|
|||
os.is_writable_folder(output_folder) or {
|
||||
// An early error here, is better than an unclear C error later:
|
||||
verror(err.msg)
|
||||
exit(1)
|
||||
}
|
||||
// Construct the V object from command line arguments
|
||||
mut b := new_builder(pref)
|
||||
|
@ -217,9 +216,7 @@ pub fn (v Builder) get_builtin_files() []string {
|
|||
}
|
||||
}
|
||||
// Panic. We couldn't find the folder.
|
||||
verror('`builtin/` not included on module lookup path.
|
||||
Did you forget to add vlib to the path? (Use @vlib for default vlib)')
|
||||
panic('Unreachable code reached.')
|
||||
verror('`builtin/` not included on module lookup path.\nDid you forget to add vlib to the path? (Use @vlib for default vlib)')
|
||||
}
|
||||
|
||||
pub fn (v &Builder) get_user_files() []string {
|
||||
|
@ -259,10 +256,7 @@ pub fn (v &Builder) get_user_files() []string {
|
|||
is_test := v.pref.is_test
|
||||
mut is_internal_module_test := false
|
||||
if is_test {
|
||||
tcontent := os.read_file(dir) or {
|
||||
verror('$dir does not exist')
|
||||
exit(0)
|
||||
}
|
||||
tcontent := os.read_file(dir) or { verror('$dir does not exist') }
|
||||
slines := tcontent.trim_space().split_into_lines()
|
||||
for sline in slines {
|
||||
line := sline.trim_space()
|
||||
|
@ -290,7 +284,6 @@ pub fn (v &Builder) get_user_files() []string {
|
|||
does_exist := os.exists(dir)
|
||||
if !does_exist {
|
||||
verror("$dir doesn't exist")
|
||||
exit(1)
|
||||
}
|
||||
is_real_file := does_exist && !os.is_dir(dir)
|
||||
resolved_link := if is_real_file && os.is_link(dir) { os.real_path(dir) } else { dir }
|
||||
|
|
|
@ -4756,10 +4756,31 @@ fn (mut c Checker) stmts(stmts []ast.Stmt) {
|
|||
if unreachable.line_nr >= 0 {
|
||||
c.error('unreachable code', unreachable)
|
||||
}
|
||||
c.find_unreachable_statements_after_noreturn_calls(stmts)
|
||||
c.scope_returns = false
|
||||
c.expected_type = ast.void_type
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) find_unreachable_statements_after_noreturn_calls(stmts []ast.Stmt) {
|
||||
mut prev_stmt_was_noreturn_call := false
|
||||
for stmt in stmts {
|
||||
match stmt {
|
||||
ast.ExprStmt {
|
||||
if stmt.expr is ast.CallExpr {
|
||||
if prev_stmt_was_noreturn_call {
|
||||
c.error('unreachable code after a [noreturn] call', stmt.pos)
|
||||
return
|
||||
}
|
||||
prev_stmt_was_noreturn_call = stmt.expr.is_noreturn
|
||||
}
|
||||
}
|
||||
else {
|
||||
prev_stmt_was_noreturn_call = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) unwrap_generic(typ ast.Type) ast.Type {
|
||||
if typ.has_flag(.generic) {
|
||||
if t_typ := c.table.resolve_generic_to_concrete(typ, c.table.cur_fn.generic_names,
|
||||
|
|
|
@ -5,3 +5,9 @@ vlib/v/checker/tests/noreturn_with_non_empty_loop_at_end.vv:4:6: error: [noretur
|
|||
| ^
|
||||
5 | break
|
||||
6 | }
|
||||
vlib/v/checker/tests/noreturn_with_non_empty_loop_at_end.vv:18:2: error: unreachable code after a [noreturn] call
|
||||
16 | eprintln('start')
|
||||
17 | abc()
|
||||
18 | eprintln('done')
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
19 | }
|
||||
|
|
|
@ -11,3 +11,9 @@ vlib/v/checker/tests/noreturn_with_return.vv:6:2: error: [noreturn] functions sh
|
|||
| ~~~~~~
|
||||
7 | }
|
||||
8 |
|
||||
vlib/v/checker/tests/noreturn_with_return.vv:18:2: error: unreachable code after a [noreturn] call
|
||||
16 | eprintln('start')
|
||||
17 | abc()
|
||||
18 | eprintln('done')
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
19 | }
|
||||
|
|
|
@ -5,3 +5,9 @@ vlib/v/checker/tests/noreturn_without_loop_or_another_noreturn_at_end.vv:3:2: er
|
|||
| ~~~~~~~~~~~~~
|
||||
4 | }
|
||||
5 |
|
||||
vlib/v/checker/tests/noreturn_without_loop_or_another_noreturn_at_end.vv:15:2: error: unreachable code after a [noreturn] call
|
||||
13 | eprintln('start')
|
||||
14 | abc()
|
||||
15 | eprintln('done')
|
||||
| ~~~~~~~~~~~~~~~~
|
||||
16 | }
|
||||
|
|
|
@ -185,6 +185,23 @@ const c_common_macros = '
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#if !defined(VUNREACHABLE)
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#define V_GCC_VERSION (__GNUC__ * 10000L + __GNUC_MINOR__ * 100L + __GNUC_PATCHLEVEL__)
|
||||
#if (V_GCC_VERSION >= 40500L)
|
||||
#define VUNREACHABLE() do { __builtin_unreachable(); } while (0)
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__clang__) && defined(__has_builtin)
|
||||
#if __has_builtin(__builtin_unreachable)
|
||||
#define VUNREACHABLE() do { __builtin_unreachable(); } while (0)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef VUNREACHABLE
|
||||
#define VUNREACHABLE() do { } while (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//likely and unlikely macros
|
||||
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
|
||||
#define _likely_(x) __builtin_expect(x,1)
|
||||
|
|
|
@ -527,6 +527,10 @@ fn (mut g Gen) call_expr(node ast.CallExpr) {
|
|||
g.write('\n $cur_line $tmp_opt')
|
||||
}
|
||||
}
|
||||
if node.is_noreturn {
|
||||
g.writeln(';')
|
||||
g.write('VUNREACHABLE()')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||
|
|
|
@ -300,7 +300,7 @@ pub fn (g JsGen) hashes() string {
|
|||
return res
|
||||
}
|
||||
|
||||
[inline]
|
||||
[noreturn]
|
||||
fn verror(msg string) {
|
||||
eprintln('jsgen error: $msg')
|
||||
exit(1)
|
||||
|
|
|
@ -802,10 +802,7 @@ fn (mut g Gen) assign_stmt(node ast.AssignStmt) {
|
|||
match node.left_types[i] {
|
||||
7 { // ast.IndexExpr {
|
||||
ie := node.left[i] as ast.IndexExpr
|
||||
bracket := name.index('[') or {
|
||||
verror('bracket expected')
|
||||
exit(1)
|
||||
}
|
||||
bracket := name.index('[') or { verror('bracket expected') }
|
||||
var_name := name[0..bracket]
|
||||
mut dest := g.get_var_offset(var_name)
|
||||
index := ie.index as ast.IntegerLiteral
|
||||
|
|
|
@ -3218,6 +3218,7 @@ fn (p &Parser) new_true_expr() ast.Expr {
|
|||
}
|
||||
}
|
||||
|
||||
[noreturn]
|
||||
fn verror(s string) {
|
||||
util.verror('parser error', s)
|
||||
}
|
||||
|
|
|
@ -1399,6 +1399,7 @@ fn (mut s Scanner) vet_error(msg string, fix vet.FixKind) {
|
|||
s.vet_errors << ve
|
||||
}
|
||||
|
||||
[noreturn]
|
||||
pub fn verror(s string) {
|
||||
util.verror('scanner error', s)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue