From a9b54e9b98764d5da875e794dea7b880b3e1389f Mon Sep 17 00:00:00 2001 From: crthpl <56052645+crthpl@users.noreply.github.com> Date: Tue, 30 Aug 2022 00:28:47 -0700 Subject: [PATCH] cgen: add `__addr` (bootstraps #14818) (#15585) --- vlib/v/checker/fn.v | 12 ++++++++++++ vlib/v/checker/tests/addr.out | 7 +++++++ vlib/v/checker/tests/addr.vv | 5 +++++ vlib/v/gen/c/fn.v | 11 +++++++++-- vlib/v/gen/c/testdata/addr.c.must_have | 1 + vlib/v/gen/c/testdata/addr.vv | 23 +++++++++++++++++++++++ vlib/v/tests/addr_test.v | 23 +++++++++++++++++++++++ 7 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 vlib/v/checker/tests/addr.out create mode 100644 vlib/v/checker/tests/addr.vv create mode 100644 vlib/v/gen/c/testdata/addr.c.must_have create mode 100644 vlib/v/gen/c/testdata/addr.vv create mode 100644 vlib/v/tests/addr_test.v diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 2cc04f5f6..09932267b 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -571,6 +571,18 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ret_type := typ.typ.set_flag(.optional) node.return_type = ret_type return ret_type + } else if fn_name == '__addr' { + if !c.inside_unsafe { + c.error('`__addr` must be called from an unsafe block', node.pos) + } + if node.args.len != 1 { + c.error('`__addr` requires 1 argument', node.pos) + return ast.void_type + } + typ := c.expr(node.args[0].expr) + node.args[0].typ = typ + node.return_type = typ.ref() + return node.return_type } // look for function in format `mod.fn` or `fn` (builtin) mut func := ast.Fn{} diff --git a/vlib/v/checker/tests/addr.out b/vlib/v/checker/tests/addr.out new file mode 100644 index 000000000..8431f111e --- /dev/null +++ b/vlib/v/checker/tests/addr.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/addr.vv:3:7: error: `__addr` must be called from an unsafe block + 1 | fn main() { + 2 | a := 4 + 3 | b := __addr(a) + | ~~~~~~~~~ + 4 | assert *b == 4 + 5 | } diff --git a/vlib/v/checker/tests/addr.vv b/vlib/v/checker/tests/addr.vv new file mode 100644 index 000000000..7921828ba --- /dev/null +++ b/vlib/v/checker/tests/addr.vv @@ -0,0 +1,5 @@ +fn main() { + a := 4 + b := __addr(a) + assert *b == 4 +} diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 18b2aefb9..b53af8918 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -1221,6 +1221,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { name = '' json_obj = tmp2 } + if name == '__addr' { + name = '&' + } if node.language == .c { // Skip "C." name = util.no_dots(name[2..]) @@ -1376,7 +1379,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { g.write(')') } mut tmp_cnt_save := -1 - g.write('(') + if name != '&' { + g.write('(') + } if is_json_fn { g.write(json_obj) } else { @@ -1395,7 +1400,9 @@ fn (mut g Gen) fn_call(node ast.CallExpr) { g.call_args(node) } } - g.write(')') + if name != '&' { + g.write(')') + } if tmp_cnt_save >= 0 { g.writeln(';') g.keep_alive_call_postgen(node, tmp_cnt_save) diff --git a/vlib/v/gen/c/testdata/addr.c.must_have b/vlib/v/gen/c/testdata/addr.c.must_have new file mode 100644 index 000000000..b42078af8 --- /dev/null +++ b/vlib/v/gen/c/testdata/addr.c.must_have @@ -0,0 +1 @@ +int* b = &a; diff --git a/vlib/v/gen/c/testdata/addr.vv b/vlib/v/gen/c/testdata/addr.vv new file mode 100644 index 000000000..a342e6b3f --- /dev/null +++ b/vlib/v/gen/c/testdata/addr.vv @@ -0,0 +1,23 @@ +struct AA { +mut: + a int +} + +fn test_addr() { + mut a := 4 + b := unsafe { __addr(a) } + a = 3 + assert *b == 3 + + mut c := [3, 4, 5] + d := unsafe { __addr(c[1]) } + c[1] = 3 + assert *d == 3 + + mut e := AA{ + a: 4 + } + f := unsafe { __addr(e.a) } + e.a = 3 + assert *f == 3 +} diff --git a/vlib/v/tests/addr_test.v b/vlib/v/tests/addr_test.v new file mode 100644 index 000000000..a342e6b3f --- /dev/null +++ b/vlib/v/tests/addr_test.v @@ -0,0 +1,23 @@ +struct AA { +mut: + a int +} + +fn test_addr() { + mut a := 4 + b := unsafe { __addr(a) } + a = 3 + assert *b == 3 + + mut c := [3, 4, 5] + d := unsafe { __addr(c[1]) } + c[1] = 3 + assert *d == 3 + + mut e := AA{ + a: 4 + } + f := unsafe { __addr(e.a) } + e.a = 3 + assert *f == 3 +} -- 2.30.2