From 03525843a062414a9099a5f392773f2083bceb93 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 18 May 2020 22:54:08 +0200 Subject: [PATCH] parser: do not allow calling private functions --- vlib/builtin/cfns.c.v | 2 +- vlib/os/os.v | 2 +- vlib/strconv/atoi.v | 2 +- vlib/time/time_nix.c.v | 2 +- vlib/time/time_windows.c.v | 2 +- vlib/v/checker/checker.v | 66 +++++++++++++++++++++----------------- vlib/v/parser/fn.v | 1 + vlib/v/util/scanning.v | 10 +++--- vlib/v/util/util.v | 2 +- 9 files changed, 49 insertions(+), 40 deletions(-) diff --git a/vlib/builtin/cfns.c.v b/vlib/builtin/cfns.c.v index ba46743ec0..a3e1c66d0e 100644 --- a/vlib/builtin/cfns.c.v +++ b/vlib/builtin/cfns.c.v @@ -31,7 +31,7 @@ fn C.backtrace_symbols(a &voidptr, size int) &charptr fn C.backtrace_symbols_fd(a &voidptr, size int, fd int) // -fn proc_pidpath(int, voidptr, int) int +pub fn proc_pidpath(int, voidptr, int) int fn C.realpath(byteptr, byteptr) &char diff --git a/vlib/os/os.v b/vlib/os/os.v index 807514e28e..ab86dbf195 100644 --- a/vlib/os/os.v +++ b/vlib/os/os.v @@ -836,7 +836,7 @@ pub fn on_segfault(f voidptr) { fn C.getpid() int -fn C.proc_pidpath(int, byteptr, int) int +//fn C.proc_pidpath(int, byteptr, int) int fn C.readlink() int diff --git a/vlib/strconv/atoi.v b/vlib/strconv/atoi.v index 198427cab8..97ba9e5eda 100644 --- a/vlib/strconv/atoi.v +++ b/vlib/strconv/atoi.v @@ -12,7 +12,7 @@ const ( max_u64 = u64(C.UINT64_MAX)// as u64 // use this until we add support ) -fn byte_to_lower(c byte) byte { +pub fn byte_to_lower(c byte) byte { return c | (`x` - `X`) } diff --git a/vlib/time/time_nix.c.v b/vlib/time/time_nix.c.v index da210c5c47..c1f366a6f9 100644 --- a/vlib/time/time_nix.c.v +++ b/vlib/time/time_nix.c.v @@ -29,7 +29,7 @@ struct C.timespec { // the first arg is defined in include/bits/types.h as `__S32_TYPE`, which is `int` fn C.clock_gettime(int, &C.timespec) -fn sys_mono_now() u64 { +pub fn sys_mono_now() u64 { $if macos { return sys_mono_now_darwin() } $else { diff --git a/vlib/time/time_windows.c.v b/vlib/time/time_windows.c.v index 66b7324e66..47f8298290 100644 --- a/vlib/time/time_windows.c.v +++ b/vlib/time/time_windows.c.v @@ -41,7 +41,7 @@ fn init_win_time_start() u64 { return s } -fn sys_mono_now() u64 { +pub fn sys_mono_now() u64 { tm := u64(0) C.QueryPerformanceCounter(&tm) // XP or later never fail return (tm - start_time) * 1_000_000_000 / freq_time diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 06dba3e4db..2772414cd9 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -878,6 +878,10 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { call_expr.pos) } } + if !f.is_pub && !f.is_c && !c.is_builtin_mod && !c.pref.is_test && f.mod != c.mod && f.name != + '' && f.mod != '' { + c.warn('function `$f.name` is private. curmod=$c.mod fmod=$f.mod', call_expr.pos) + } call_expr.return_type = f.return_type if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines { call_expr.should_be_skipped = true @@ -1483,35 +1487,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { c.check_expr_opt_call(it.expr, etype, false) } ast.FnDecl { - if !it.is_c && !it.is_js && !c.is_builtin_mod { - c.check_valid_snake_case(it.name, 'function name', it.pos) - } - if it.is_method { - sym := c.table.get_type_symbol(it.receiver.typ) - if sym.kind == .interface_ { - c.error('interfaces cannot be used as method receiver', it.receiver_pos) - } - // if sym.has_method(it.name) { - // c.warn('duplicate method `$it.name`', it.pos) - // } - } - if !it.is_c { - // Make sure all types are valid - for arg in it.args { - sym := c.table.get_type_symbol(arg.typ) - if sym.kind == .placeholder { - c.error('unknown type `$sym.name`', it.pos) - } - } - } - c.expected_type = table.void_type - c.fn_return_type = it.return_type - c.stmts(it.stmts) - if !it.is_c && !it.is_js && !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 + c.fn_decl(it) } ast.ForCStmt { c.in_for_count++ @@ -2312,3 +2288,35 @@ fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool) fn (c &Checker) fileis(s string) bool { return c.file.path.contains(s) } + +fn (mut c Checker) fn_decl(it ast.FnDecl) { + if !it.is_c && !it.is_js && !c.is_builtin_mod { + c.check_valid_snake_case(it.name, 'function name', it.pos) + } + if it.is_method { + sym := c.table.get_type_symbol(it.receiver.typ) + if sym.kind == .interface_ { + c.error('interfaces cannot be used as method receiver', it.receiver_pos) + } + // if sym.has_method(it.name) { + // c.warn('duplicate method `$it.name`', it.pos) + // } + } + if !it.is_c { + // Make sure all types are valid + for arg in it.args { + sym := c.table.get_type_symbol(arg.typ) + if sym.kind == .placeholder { + c.error('unknown type `$sym.name`', it.pos) + } + } + } + c.expected_type = table.void_type + c.fn_return_type = it.return_type + c.stmts(it.stmts) + if !it.is_c && !it.is_js && !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 +} diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 270d7ae2ec..33a1831054 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -255,6 +255,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { is_generic: is_generic is_pub: is_pub ctdefine: ctdefine + mod: p.mod }) } // Body diff --git a/vlib/v/util/scanning.v b/vlib/v/util/scanning.v index 865ff6907e..9fc7e7e39b 100644 --- a/vlib/v/util/scanning.v +++ b/vlib/v/util/scanning.v @@ -3,21 +3,21 @@ module util import os [inline] -fn is_name_char(c byte) bool { +pub fn is_name_char(c byte) bool { return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` } [inline] -fn is_func_char(c byte) bool { +pub fn is_func_char(c byte) bool { return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` || c.is_digit() } [inline] -fn is_nl(c byte) bool { +pub fn is_nl(c byte) bool { return c == `\r` || c == `\n` } -fn contains_capital(s string) bool { +pub fn contains_capital(s string) bool { for c in s { if c >= `A` && c <= `Z` { return true @@ -28,7 +28,7 @@ fn contains_capital(s string) bool { // HTTPRequest bad // HttpRequest good -fn good_type_name(s string) bool { +pub fn good_type_name(s string) bool { if s.len < 4 { return true } diff --git a/vlib/v/util/util.v b/vlib/v/util/util.v index 68d3c382a6..c54e798308 100644 --- a/vlib/v/util/util.v +++ b/vlib/v/util/util.v @@ -222,7 +222,7 @@ fn imax(a, b int) int { } } -fn replace_op(s string) string { +pub fn replace_op(s string) string { last_char := s[s.len - 1] suffix := match last_char { `+` { '_plus' }