mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: warn if unsafe method called outside unsafe block (#5863)
This commit is contained in:
parent
90d9040e6e
commit
105a0e015e
@ -331,12 +331,18 @@ pub fn (a &array) clone() array {
|
||||
if a.element_size == sizeof(array) {
|
||||
for i in 0..a.len {
|
||||
ar := array{}
|
||||
C.memcpy(&ar, a.get_unsafe(i), sizeof(array))
|
||||
unsafe {
|
||||
C.memcpy(&ar, a.get_unsafe(i), sizeof(array))
|
||||
}
|
||||
ar_clone := ar.clone()
|
||||
arr.set_unsafe(i, &ar_clone)
|
||||
unsafe {
|
||||
arr.set_unsafe(i, &ar_clone)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
C.memcpy(byteptr(arr.data), a.data, a.cap * a.element_size)
|
||||
unsafe {
|
||||
C.memcpy(byteptr(arr.data), a.data, a.cap * a.element_size)
|
||||
}
|
||||
}
|
||||
return arr
|
||||
}
|
||||
@ -681,7 +687,9 @@ pub fn compare_f32(a, b &f32) int {
|
||||
pub fn (a array) pointers() []voidptr {
|
||||
mut res := []voidptr{}
|
||||
for i in 0..a.len {
|
||||
res << a.get_unsafe(i)
|
||||
unsafe {
|
||||
res << a.get_unsafe(i)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
@ -517,7 +517,7 @@ pub fn (m map) clone() map {
|
||||
cap: m.cap
|
||||
cached_hashbits: m.cached_hashbits
|
||||
shift: m.shift
|
||||
key_values: m.key_values.clone()
|
||||
key_values: unsafe {m.key_values.clone()}
|
||||
metas: &u32(malloc(int(metas_size)))
|
||||
extra_metas: m.extra_metas
|
||||
len: m.len
|
||||
|
@ -1201,11 +1201,14 @@ pub fn (u ustring) at(idx int) string {
|
||||
return u.substr(idx, idx + 1)
|
||||
}
|
||||
|
||||
[unsafe_fn]
|
||||
fn (u &ustring) free() {
|
||||
$if prealloc {
|
||||
return
|
||||
}
|
||||
u.runes.free()
|
||||
unsafe {
|
||||
u.runes.free()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn (c byte) is_digit() bool {
|
||||
|
@ -42,17 +42,22 @@ pub fn compile(command string, pref &pref.Preferences) {
|
||||
println('compilation took: $sw.elapsed().milliseconds() ms')
|
||||
}
|
||||
// running does not require the parsers anymore
|
||||
b.myfree()
|
||||
unsafe {
|
||||
b.myfree()
|
||||
}
|
||||
if pref.is_test || pref.is_run {
|
||||
b.run_compiled_executable_and_exit()
|
||||
}
|
||||
}
|
||||
|
||||
// Temporary, will be done by -autofree
|
||||
[unsafe_fn]
|
||||
fn (mut b Builder) myfree() {
|
||||
// for file in b.parsed_files {
|
||||
// }
|
||||
b.parsed_files.free()
|
||||
unsafe {
|
||||
b.parsed_files.free()
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut b Builder) run_compiled_executable_and_exit() {
|
||||
|
@ -954,6 +954,10 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||
}
|
||||
}
|
||||
}
|
||||
if method.is_unsafe && !c.inside_unsafe {
|
||||
c.warn('method `${left_type_sym.name}.$method_name` must be called from an `unsafe` block',
|
||||
call_expr.pos)
|
||||
}
|
||||
// TODO: typ optimize.. this node can get processed more than once
|
||||
if call_expr.expected_arg_types.len == 0 {
|
||||
for i in 1 .. method.args.len {
|
||||
|
@ -123,6 +123,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
p.top_level_statement_start()
|
||||
start_pos := p.tok.position()
|
||||
is_deprecated := 'deprecated' in p.attrs
|
||||
is_unsafe := 'unsafe_fn' in p.attrs
|
||||
is_pub := p.tok.kind == .key_pub
|
||||
if is_pub {
|
||||
p.next()
|
||||
@ -250,6 +251,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
is_generic: is_generic
|
||||
is_pub: is_pub
|
||||
is_deprecated: is_deprecated
|
||||
is_unsafe: is_unsafe
|
||||
ctdefine: ctdefine
|
||||
mod: p.mod
|
||||
attrs: p.attrs
|
||||
@ -271,12 +273,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
|
||||
args: args
|
||||
return_type: return_type
|
||||
is_variadic: is_variadic
|
||||
language: language
|
||||
is_generic: is_generic
|
||||
is_pub: is_pub
|
||||
is_deprecated: is_deprecated
|
||||
is_unsafe: is_unsafe
|
||||
ctdefine: ctdefine
|
||||
mod: p.mod
|
||||
language: language
|
||||
})
|
||||
}
|
||||
// Body
|
||||
|
@ -29,6 +29,7 @@ pub:
|
||||
is_generic bool
|
||||
is_pub bool
|
||||
is_deprecated bool
|
||||
is_unsafe bool
|
||||
mod string
|
||||
ctdefine string // compile time define. myflag, when [if myflag] tag
|
||||
attrs []string
|
||||
|
34
vlib/v/tests/unsafe.out
Normal file
34
vlib/v/tests/unsafe.out
Normal file
@ -0,0 +1,34 @@
|
||||
unsafe.v:4:6: warning: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
2 | v := 5
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
| ~~
|
||||
5 | p += 2
|
||||
6 | _ := v
|
||||
unsafe.v:5:7: warning: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
3 | mut p := &v
|
||||
4 | p++
|
||||
5 | p += 2
|
||||
| ~~
|
||||
6 | _ := v
|
||||
7 | }
|
||||
unsafe.v:11:14: warning: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
9 | fn test_ptr_infix() {
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
| ^
|
||||
12 | q = q + 3
|
||||
13 | _ := q
|
||||
unsafe.v:12:9: warning: pointer arithmetic is only allowed in `unsafe` blocks
|
||||
10 | v := 4
|
||||
11 | mut q := &v - 1
|
||||
12 | q = q + 3
|
||||
| ^
|
||||
13 | _ := q
|
||||
14 | _ := v
|
||||
unsafe.v:24:7: warning: method `S1.f` must be called from an `unsafe` block
|
||||
22 | fn test_funcs() {
|
||||
23 | s := S1{}
|
||||
24 | s.f()
|
||||
| ~~~
|
||||
25 | }
|
25
vlib/v/tests/unsafe.v
Normal file
25
vlib/v/tests/unsafe.v
Normal file
@ -0,0 +1,25 @@
|
||||
fn test_ptr_assign() {
|
||||
v := 5
|
||||
mut p := &v
|
||||
p++
|
||||
p += 2
|
||||
_ := v
|
||||
}
|
||||
|
||||
fn test_ptr_infix() {
|
||||
v := 4
|
||||
mut q := &v - 1
|
||||
q = q + 3
|
||||
_ := q
|
||||
_ := v
|
||||
}
|
||||
|
||||
struct S1 {}
|
||||
|
||||
[unsafe_fn]
|
||||
fn (s S1) f(){}
|
||||
|
||||
fn test_funcs() {
|
||||
s := S1{}
|
||||
s.f()
|
||||
}
|
Loading…
Reference in New Issue
Block a user