From ccf6285f822677560d1aa37ef606f043d01b5c1d Mon Sep 17 00:00:00 2001 From: Enzo Date: Sat, 11 Sep 2021 13:25:38 +0200 Subject: [PATCH] checker: allow mut arg on C functions (#11430) --- vlib/v/checker/checker.v | 2 +- vlib/v/parser/fn.v | 5 +++++ vlib/v/parser/parser.v | 1 + vlib/v/tests/c_function_mut_param/code.c | 3 +++ vlib/v/tests/c_function_mut_param/code_test.v | 12 ++++++++++++ vlib/v/tests/c_function_mut_param/v.mod | 7 +++++++ 6 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/c_function_mut_param/code.c create mode 100644 vlib/v/tests/c_function_mut_param/code_test.v create mode 100644 vlib/v/tests/c_function_mut_param/v.mod diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index f19b12caee..1a76006aa3 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2938,7 +2938,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr) ast.Type { c.error('function with `shared` arguments cannot be called inside `lock`/`rlock` block', call_arg.pos) } - if call_arg.is_mut && func.language == .v { + if call_arg.is_mut { to_lock, pos := c.fail_if_immutable(call_arg.expr) if !call_arg.expr.is_lvalue() { c.error('cannot pass expression as `mut`', call_arg.expr.position()) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index e2eefa8478..82f54daeee 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -216,6 +216,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { } else if p.tok.kind == .name && p.tok.lit == 'JS' { language = .js } + p.fn_language = language if language != .v { for fna in p.attrs { if fna.name == 'export' { @@ -249,6 +250,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // rec.language was initialized with language variable. // So language is changed only if rec.language has been changed. language = rec.language + p.fn_language = language } mut name := '' name_pos := p.tok.position() @@ -994,6 +996,9 @@ fn (mut p Parser) check_fn_mutable_arguments(typ ast.Type, pos token.Position) { p.check_fn_mutable_arguments(atyp, pos) return } + if p.fn_language == .c { + return + } p.error_with_pos( 'mutable arguments are only allowed for arrays, interfaces, maps, pointers, structs or their aliases\n' + 'return values instead: `fn foo(mut n $sym.name) {` => `fn foo(n $sym.name) $sym.name {`', diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 6d00b26a5d..cf6ef95222 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -33,6 +33,7 @@ mut: peek_tok token.Token table &ast.Table language ast.Language + fn_language ast.Language // .c for `fn C.abcd()` declarations inside_test_file bool // when inside _test.v or _test.vv file inside_if bool inside_if_expr bool diff --git a/vlib/v/tests/c_function_mut_param/code.c b/vlib/v/tests/c_function_mut_param/code.c new file mode 100644 index 0000000000..d233a68851 --- /dev/null +++ b/vlib/v/tests/c_function_mut_param/code.c @@ -0,0 +1,3 @@ +void mut_arg(const byte *_key, size_t *val) { + *val = 5; +} diff --git a/vlib/v/tests/c_function_mut_param/code_test.v b/vlib/v/tests/c_function_mut_param/code_test.v new file mode 100644 index 0000000000..c95fbc29b6 --- /dev/null +++ b/vlib/v/tests/c_function_mut_param/code_test.v @@ -0,0 +1,12 @@ +module main + +#include "@VMODROOT/code.c" + +fn C.mut_arg(key &byte, mut val usize) + +fn test_c_function_mut_param() { + key := &byte(1) + mut val := usize(1) + C.mut_arg(key, mut &val) + assert val == usize(5) +} diff --git a/vlib/v/tests/c_function_mut_param/v.mod b/vlib/v/tests/c_function_mut_param/v.mod new file mode 100644 index 0000000000..a00af8bd16 --- /dev/null +++ b/vlib/v/tests/c_function_mut_param/v.mod @@ -0,0 +1,7 @@ +Module { + name: 'c_function_mut_param' + description: '' + version: '' + license: '' + dependencies: [] +}