From 6b3724df3a7f1d9785e0bcfeb07b36c79b9f64d2 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 13 Jan 2025 19:01:43 +0300 Subject: [PATCH] checker: do not allow auto reference of voidptr params --- vlib/os/file.c.v | 1 + vlib/os/os.c.v | 2 +- vlib/time/time_windows.c.v | 2 +- vlib/v/checker/autocomplete.v | 7 ++++++- vlib/v/checker/checker.v | 5 ----- vlib/v/checker/fn.v | 24 ++++++++++++++++++----- vlib/v/checker/tests/auto_ref_voidptr.out | 7 +++++++ vlib/v/checker/tests/auto_ref_voidptr.vv | 11 +++++++++++ vlib/v/parser/parser.v | 2 +- 9 files changed, 47 insertions(+), 14 deletions(-) create mode 100644 vlib/v/checker/tests/auto_ref_voidptr.out create mode 100644 vlib/v/checker/tests/auto_ref_voidptr.vv diff --git a/vlib/os/file.c.v b/vlib/os/file.c.v index 2e4605c53..8eecc0e59 100644 --- a/vlib/os/file.c.v +++ b/vlib/os/file.c.v @@ -503,6 +503,7 @@ pub fn (f &File) read_bytes_into(pos u64, mut buf []u8) !int { return nbytes } $else { C.fseeko(f.cfile, pos, C.SEEK_SET) + // TODO(alex): require casts for voidptrs? &C.FILE(f.cfile) nbytes := fread(buf.data, 1, buf.len, f.cfile)! $if debug { C.fseeko(f.cfile, 0, C.SEEK_SET) diff --git a/vlib/os/os.c.v b/vlib/os/os.c.v index 08a5ff3d3..a5ebd2ee0 100644 --- a/vlib/os/os.c.v +++ b/vlib/os/os.c.v @@ -278,7 +278,7 @@ pub fn vfopen(path string, mode string) !&C.FILE { } $else { fp = C.fopen(&char(path.str), &char(mode.str)) } - if isnil(fp) { + if isnil(voidptr(fp)) { return error_posix(msg: 'failed to open file "${path}"') } else { return fp diff --git a/vlib/time/time_windows.c.v b/vlib/time/time_windows.c.v index 72c394a27..c4b2e0665 100644 --- a/vlib/time/time_windows.c.v +++ b/vlib/time/time_windows.c.v @@ -96,7 +96,7 @@ fn vpc_now() u64 { fn local_as_unix_time() i64 { t := C.time(0) tm := C.localtime(&t) - return make_unix_time(tm) + return make_unix_time(*tm) } // local - return the time `t`, converted to the currently active local timezone diff --git a/vlib/v/checker/autocomplete.v b/vlib/v/checker/autocomplete.v index dad8d7055..a25417463 100644 --- a/vlib/v/checker/autocomplete.v +++ b/vlib/v/checker/autocomplete.v @@ -6,6 +6,11 @@ import strings import v.ast import os +struct ACFieldMethod { + name string + typ string +} + fn (mut c Checker) ident_autocomplete(node ast.Ident) { // Mini LS hack (v -line-info "a.v:16") println( @@ -81,7 +86,7 @@ fn (mut c Checker) ident_autocomplete(node ast.Ident) { } } -fn build_method_summary(method &ast.Fn) string { +fn build_method_summary(method ast.Fn) string { mut s := method.name + '(' for i, param in method.params { s += param.name diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 96d5cb918..4a1776134 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3904,11 +3904,6 @@ fn (mut c Checker) at_expr(mut node ast.AtExpr) ast.Type { return ast.string_type } -struct ACFieldMethod { - name string - typ string -} - fn (mut c Checker) resolve_var_fn(func &ast.Fn, mut node ast.Ident, name string) ast.Type { mut fn_type := ast.new_type(c.table.find_or_register_fn_type(func, false, true)) if func.generic_names.len > 0 { diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index a70a1712f..419eaac6a 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1754,11 +1754,25 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast. call_arg.pos) } // Warn about automatic (de)referencing, which will be removed soon. - if func.language != .c && !c.inside_unsafe && arg_typ.nr_muls() != param.typ.nr_muls() - && !(call_arg.is_mut && param.is_mut) && !(!call_arg.is_mut && !param.is_mut) - && param.typ !in [ast.byteptr_type, ast.charptr_type, ast.voidptr_type, ast.nil_type] { - c.warn('automatic referencing/dereferencing is deprecated and will be removed soon (got: ${arg_typ.nr_muls()} references, expected: ${param.typ.nr_muls()} references)', - call_arg.pos) + if func.language != .c && !c.inside_unsafe && !(call_arg.is_mut && param.is_mut) { + if arg_typ.nr_muls() != param.typ.nr_muls() + && param.typ !in [ast.byteptr_type, ast.charptr_type, ast.voidptr_type, ast.nil_type] + && arg_typ != ast.voidptr_type && !(!call_arg.is_mut && !param.is_mut) //&& !(!call_arg.is_mut && !param.is_mut) + { + c.warn('automatic referencing/dereferencing is deprecated and will be removed soon (got: ${arg_typ.nr_muls()} references, expected: ${param.typ.nr_muls()} references)', + call_arg.pos) + } + // A special case of the check to not allow voidptr params like in the recently reported raylib + // bug with fn... + // fn f(p &Foo) => f(foo) -- do not allow this, force f(&foo) + // if !c.is_builtin_mod + if param.typ == ast.voidptr_type && func.language == .v + && arg_typ !in [ast.voidptr_type, ast.nil_type] && arg_typ.nr_muls() == 0 + && func.name !in ['isnil', 'ptr_str'] && !func.name.starts_with('json.') + && arg_typ_sym.kind !in [.float_literal, .int_literal] && !c.pref.backend.is_js() { + c.warn('automatic ${arg_typ_sym.name} referencing/dereferencing into voidptr is deprecated and will be removed soon; use `foo(&x)` instead of `foo(x)`', + call_arg.pos) + } } } if func.generic_names.len != node.concrete_types.len { diff --git a/vlib/v/checker/tests/auto_ref_voidptr.out b/vlib/v/checker/tests/auto_ref_voidptr.out new file mode 100644 index 000000000..a3087290d --- /dev/null +++ b/vlib/v/checker/tests/auto_ref_voidptr.out @@ -0,0 +1,7 @@ +auto_ref_voidptr.vv:9:9: warning: automatic Aa referencing/dereferencing into voidptr is deprecated and will be removed soon; use `foo(&x)` instead of `foo(x)` + 7 | fn main() { + 8 | a := Aa{} + 9 | foo(3, a) + | ^ + 10 | // foo2(a) + 11 | } diff --git a/vlib/v/checker/tests/auto_ref_voidptr.vv b/vlib/v/checker/tests/auto_ref_voidptr.vv new file mode 100644 index 000000000..05d27717c --- /dev/null +++ b/vlib/v/checker/tests/auto_ref_voidptr.vv @@ -0,0 +1,11 @@ +fn foo(x int, p voidptr) {} + +fn foo2(p &Aa) {} + +struct Aa {} + +fn main() { + a := Aa{} + foo(3, a) + // foo2(a) +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index c78251bdc..10f1bbf16 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -2597,7 +2597,7 @@ fn (p &Parser) is_generic_call() bool { const valid_tokens_inside_types = [token.Kind.lsbr, .rsbr, .name, .dot, .comma, .key_fn, .lt] fn (mut p Parser) is_generic_cast() bool { - if !ast.type_can_start_with_token(p.tok) { + if !ast.type_can_start_with_token(&p.tok) { return false } mut i := 0 -- 2.39.5