Skip to content

Commit 9a01667

Browse files
authored
cgen: add @[reused] attribute to mark methods, reusing the receiver memory on return (needed for autofree) (fix #25221) (#25235)
1 parent 2b4253c commit 9a01667

5 files changed

Lines changed: 46 additions & 9 deletions

File tree

vlib/builtin/string_charptr_byteptr_helpers.v

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ module builtin
33
// Note: this file will be removed soon
44

55
// byteptr.vbytes() - makes a V []u8 structure from a C style memory buffer. Note: the data is reused, NOT copied!
6-
@[unsafe]
6+
@[reused; unsafe]
77
pub fn (data byteptr) vbytes(len int) []u8 {
88
return unsafe { voidptr(data).vbytes(len) }
99
}
1010

1111
// vstring converts a C style string to a V string. Note: the string data is reused, NOT copied.
1212
// strings returned from this function will be normal V strings beside that (i.e. they would be
1313
// freed by V's -autofree mechanism, when they are no longer used).
14-
@[unsafe]
14+
@[reused; unsafe]
1515
pub fn (bp byteptr) vstring() string {
1616
return string{
1717
str: bp
@@ -21,7 +21,7 @@ pub fn (bp byteptr) vstring() string {
2121

2222
// vstring_with_len converts a C style string to a V string.
2323
// Note: the string data is reused, NOT copied.
24-
@[unsafe]
24+
@[reused; unsafe]
2525
pub fn (bp byteptr) vstring_with_len(len int) string {
2626
return string{
2727
str: bp
@@ -32,7 +32,7 @@ pub fn (bp byteptr) vstring_with_len(len int) string {
3232

3333
// vstring converts C char* to V string.
3434
// Note: the string data is reused, NOT copied.
35-
@[unsafe]
35+
@[reused; unsafe]
3636
pub fn (cp charptr) vstring() string {
3737
return string{
3838
str: byteptr(cp)
@@ -43,7 +43,7 @@ pub fn (cp charptr) vstring() string {
4343

4444
// vstring_with_len converts C char* to V string.
4545
// Note: the string data is reused, NOT copied.
46-
@[unsafe]
46+
@[reused; unsafe]
4747
pub fn (cp charptr) vstring_with_len(len int) string {
4848
return string{
4949
str: byteptr(cp)
@@ -59,7 +59,7 @@ pub fn (cp charptr) vstring_with_len(len int) string {
5959
// This is suitable for readonly strings, C string literals etc,
6060
// that can be read by the V program, but that should not be
6161
// managed by it, for example `os.args` is implemented using it.
62-
@[unsafe]
62+
@[reused; unsafe]
6363
pub fn (bp byteptr) vstring_literal() string {
6464
return string{
6565
str: bp
@@ -70,7 +70,7 @@ pub fn (bp byteptr) vstring_literal() string {
7070

7171
// vstring_with_len converts a C style string to a V string.
7272
// Note: the string data is reused, NOT copied.
73-
@[unsafe]
73+
@[reused; unsafe]
7474
pub fn (bp byteptr) vstring_literal_with_len(len int) string {
7575
return string{
7676
str: bp
@@ -82,7 +82,7 @@ pub fn (bp byteptr) vstring_literal_with_len(len int) string {
8282
// vstring_literal converts C char* to V string.
8383
// See also vstring_literal defined on byteptr for more details.
8484
// Note: the string data is reused, NOT copied.
85-
@[unsafe]
85+
@[reused; unsafe]
8686
pub fn (cp charptr) vstring_literal() string {
8787
return string{
8888
str: byteptr(cp)
@@ -94,7 +94,7 @@ pub fn (cp charptr) vstring_literal() string {
9494
// vstring_literal_with_len converts C char* to V string.
9595
// See also vstring_literal_with_len defined on byteptr.
9696
// Note: the string data is reused, NOT copied.
97-
@[unsafe]
97+
@[reused; unsafe]
9898
pub fn (cp charptr) vstring_literal_with_len(len int) string {
9999
return string{
100100
str: byteptr(cp)

vlib/v/gen/c/autofree.v

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,21 @@ fn (mut g Gen) autofree_scope_vars2(scope &ast.Scope, start_pos int, end_pos int
9898
if obj.expr is ast.IfGuardExpr {
9999
continue
100100
}
101+
if obj.expr is ast.UnsafeExpr && obj.expr.expr is ast.CallExpr
102+
&& (obj.expr.expr as ast.CallExpr).is_method {
103+
if left_var := scope.objects[obj.expr.expr.left.str()] {
104+
if func := g.table.find_method(g.table.final_sym(left_var.typ),
105+
obj.expr.expr.name)
106+
{
107+
if func.attrs.contains('reused') && left_var is ast.Var
108+
&& left_var.expr is ast.CastExpr {
109+
if left_var.expr.expr.is_literal() {
110+
continue
111+
}
112+
}
113+
}
114+
}
115+
}
101116
g.autofree_variable(obj)
102117
}
103118
else {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
VV_LOC void main__main(void) {
2+
byteptr b = ((byteptr)("a"));
3+
Array_u8 s = byteptr_vbytes(b, 1);
4+
string _t1 = Array_u8_str(s); println(_t1); string_free(&_t1);
5+
;
6+
byteptr bb = ((byteptr)("a"));
7+
string ss = byteptr_vstring(bb);
8+
println(ss);
9+
}
10+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[97]
2+
a
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// vtest vflags: -autofree
2+
fn main() {
3+
b := byteptr(c'a')
4+
s := unsafe { b.vbytes(1) }
5+
println(s)
6+
7+
bb := byteptr(c'a')
8+
ss := unsafe { bb.vstring() }
9+
println(ss)
10+
}

0 commit comments

Comments
 (0)