mirror of
https://github.com/vlang/v.git
synced 2025-09-11 00:20:26 -04:00
checker: add fntype casting validations (#23872)
This commit is contained in:
parent
e006b65944
commit
734fde89e8
@ -14,7 +14,7 @@ type FN_NTSuspendResume = fn (voidptr) u64
|
|||||||
fn ntdll_fn(name &char) FN_NTSuspendResume {
|
fn ntdll_fn(name &char) FN_NTSuspendResume {
|
||||||
ntdll := C.GetModuleHandleA(c'NTDLL')
|
ntdll := C.GetModuleHandleA(c'NTDLL')
|
||||||
if ntdll == 0 {
|
if ntdll == 0 {
|
||||||
return FN_NTSuspendResume(0)
|
return unsafe { FN_NTSuspendResume(0) }
|
||||||
}
|
}
|
||||||
the_fn := FN_NTSuspendResume(C.GetProcAddress(ntdll, voidptr(name)))
|
the_fn := FN_NTSuspendResume(C.GetProcAddress(ntdll, voidptr(name)))
|
||||||
return the_fn
|
return the_fn
|
||||||
|
@ -3593,6 +3593,25 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
|||||||
|| c.file.is_translated) && !c.check_matching_function_symbols(final_from_sym, final_to_sym) {
|
|| c.file.is_translated) && !c.check_matching_function_symbols(final_from_sym, final_to_sym) {
|
||||||
c.error('casting a function value from one function signature, to another function signature, should be done inside `unsafe{}` blocks',
|
c.error('casting a function value from one function signature, to another function signature, should be done inside `unsafe{}` blocks',
|
||||||
node.pos)
|
node.pos)
|
||||||
|
} else if final_to_sym.kind == .function && final_from_sym.kind != .function {
|
||||||
|
if to_type.has_flag(.option) && node.expr !is ast.None {
|
||||||
|
c.error('casting number to Option function is not allowed, only compatible function or `none`',
|
||||||
|
node.pos)
|
||||||
|
} else if !(c.inside_unsafe || c.file.is_translated) {
|
||||||
|
if node.expr is ast.IntegerLiteral {
|
||||||
|
c.warn('casting number to function value should be done inside `unsafe{}` blocks',
|
||||||
|
node.pos)
|
||||||
|
} else if node.expr is ast.Nil {
|
||||||
|
c.warn('casting `nil` to function value should be done inside `unsafe{}` blocks',
|
||||||
|
node.pos)
|
||||||
|
} else if node.expr is ast.None {
|
||||||
|
if from_type.has_flag(.option) {
|
||||||
|
c.warn('cannot pass `none` to a non Option function type', node.pos)
|
||||||
|
}
|
||||||
|
} else if final_from_sym.kind != .voidptr {
|
||||||
|
c.error('invalid casting value to function', node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if to_type.is_ptr() && to_sym.kind == .alias && from_sym.kind == .map {
|
if to_type.is_ptr() && to_sym.kind == .alias && from_sym.kind == .map {
|
||||||
c.error('cannot cast to alias pointer `${c.table.type_to_str(to_type)}` because `${c.table.type_to_str(from_type)}` is a value',
|
c.error('cannot cast to alias pointer `${c.table.type_to_str(to_type)}` because `${c.table.type_to_str(from_type)}` is a value',
|
||||||
|
69
vlib/v/checker/tests/cast_fn_err.out
Normal file
69
vlib/v/checker/tests/cast_fn_err.out
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
vlib/v/checker/tests/cast_fn_err.vv:24:7: warning: casting `nil` to function value should be done inside `unsafe{}` blocks
|
||||||
|
22 | // wrong ones
|
||||||
|
23 | _ := FnType(foo)
|
||||||
|
24 | _ := FnType(nil)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:25:7: warning: casting number to function value should be done inside `unsafe{}` blocks
|
||||||
|
23 | _ := FnType(foo)
|
||||||
|
24 | _ := FnType(nil)
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
| ~~~~~~~~~
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:23:7: error: casting a function value from one function signature, to another function signature, should be done inside `unsafe{}` blocks
|
||||||
|
21 |
|
||||||
|
22 | // wrong ones
|
||||||
|
23 | _ := FnType(foo)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
24 | _ := FnType(nil)
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:24:14: error: `nil` is only allowed in `unsafe` code
|
||||||
|
22 | // wrong ones
|
||||||
|
23 | _ := FnType(foo)
|
||||||
|
24 | _ := FnType(nil)
|
||||||
|
| ~~~
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:26:7: error: invalid casting value to function
|
||||||
|
24 | _ := FnType(nil)
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
| ~~~~~~~~~~~~~
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:27:7: error: cannot cast `none` to `fn () bool`
|
||||||
|
25 | _ := FnType(0)
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
| ~~~~~~~~~~~~
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
29 | _ := ?FnType(nil)
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:28:8: error: casting number to Option function is not allowed, only compatible function or `none`
|
||||||
|
26 | _ := FnType('foo')
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
| ~~~~~~~~~
|
||||||
|
29 | _ := ?FnType(nil)
|
||||||
|
30 | _ := ?FnType(foo)
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:29:15: error: `nil` is only allowed in `unsafe` code
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
29 | _ := ?FnType(nil)
|
||||||
|
| ~~~
|
||||||
|
30 | _ := ?FnType(foo)
|
||||||
|
31 | }
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:29:8: error: casting number to Option function is not allowed, only compatible function or `none`
|
||||||
|
27 | _ := FnType(none)
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
29 | _ := ?FnType(nil)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
30 | _ := ?FnType(foo)
|
||||||
|
31 | }
|
||||||
|
vlib/v/checker/tests/cast_fn_err.vv:30:8: error: casting a function value from one function signature, to another function signature, should be done inside `unsafe{}` blocks
|
||||||
|
28 | _ := ?FnType(0)
|
||||||
|
29 | _ := ?FnType(nil)
|
||||||
|
30 | _ := ?FnType(foo)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
31 | }
|
31
vlib/v/checker/tests/cast_fn_err.vv
Normal file
31
vlib/v/checker/tests/cast_fn_err.vv
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
type FnType = fn () bool
|
||||||
|
|
||||||
|
fn foo() int {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bar() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// acceptable ones
|
||||||
|
_ := unsafe { FnType(nil) }
|
||||||
|
_ := unsafe { FnType(0) }
|
||||||
|
_ := unsafe { FnType(foo) }
|
||||||
|
_ := unsafe { FnType(bar) }
|
||||||
|
_ := FnType(bar)
|
||||||
|
_ := ?FnType(none)
|
||||||
|
_ := ?FnType(bar)
|
||||||
|
_ := unsafe { ?FnType(foo) }
|
||||||
|
|
||||||
|
// wrong ones
|
||||||
|
_ := FnType(foo)
|
||||||
|
_ := FnType(nil)
|
||||||
|
_ := FnType(0)
|
||||||
|
_ := FnType('foo')
|
||||||
|
_ := FnType(none)
|
||||||
|
_ := ?FnType(0)
|
||||||
|
_ := ?FnType(nil)
|
||||||
|
_ := ?FnType(foo)
|
||||||
|
}
|
@ -16,7 +16,7 @@ pub:
|
|||||||
fn window_resized(mut w &Window) {
|
fn window_resized(mut w &Window) {
|
||||||
window_width, window_height := 200, 100
|
window_width, window_height := 200, 100
|
||||||
|
|
||||||
if w.resize_fn != WindowResizeFn(0) {
|
if w.resize_fn != unsafe { WindowResizeFn(0) } {
|
||||||
println('fn present ${window_width} ${window_height}')
|
println('fn present ${window_width} ${window_height}')
|
||||||
w.resize_fn(w, window_width, window_height)
|
w.resize_fn(w, window_width, window_height)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user