checker: disallow assigning number to pointer (#7267)

pull/7286/head
Nick Treleaven 2020-12-12 09:42:07 +00:00 committed by GitHub
parent 5fec0d785a
commit d785e22a6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 47 additions and 22 deletions

View File

@ -140,6 +140,6 @@ fn print_backtrace_skipping_top_frames_linux(skipframes int) bool {
fn break_if_debugger_attached() {
unsafe {
mut ptr := &voidptr(0)
*ptr = 0
*ptr = voidptr(0)
}
}

View File

@ -234,7 +234,7 @@ fn break_if_debugger_attached() {
$if tinyc {
unsafe {
mut ptr := &voidptr(0)
*ptr = 0
*ptr = voidptr(0)
}
} $else {
if C.IsDebuggerPresent() {

View File

@ -425,9 +425,7 @@ fn (cb &Clipboard) get_supported_targets() []C.Atom {
}
fn new_atom(value int) &C.Atom {
mut atom := &C.Atom{}
atom = value
return atom
return unsafe {&C.Atom(value)}
}
fn create_xwindow(display &C.Display) C.Window {

View File

@ -118,7 +118,7 @@ fn load_lib(mut r live.LiveReloadInfo, new_lib_path string) {
fn protected_load_lib(mut r live.LiveReloadInfo, new_lib_path string) {
if r.live_lib != 0 {
dl.close( r.live_lib )
r.live_lib = 0
r.live_lib = C.NULL
}
r.live_lib = dl.open(new_lib_path, dl.rtld_lazy)
if r.live_lib == 0 {

View File

@ -283,9 +283,14 @@ pub fn (mut c Checker) check_expected(got table.Type, expected table.Type) ? {
if c.check_types(got, expected) {
return
}
return error(c.expected_msg(got, expected))
}
[inline]
fn (c &Checker) expected_msg(got table.Type, expected table.Type) string {
exps := c.table.type_to_str(expected)
gots := c.table.type_to_str(got)
return error('expected `$exps`, not `$gots`')
return 'expected `$exps`, not `$gots`'
}
pub fn (mut c Checker) symmetric_check(left table.Type, right table.Type) bool {

View File

@ -2173,25 +2173,31 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
}
left_sym := c.table.get_type_symbol(left_type_unwrapped)
right_sym := c.table.get_type_symbol(right_type_unwrapped)
left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
right_is_ptr := right_type.is_ptr() || right_sym.is_pointer()
if left_is_ptr && assign_stmt.op !in [.assign, .decl_assign] && !c.inside_unsafe {
// ptr op=
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
}
if c.pref.translated {
// TODO fix this in C2V instead, for example cast enums to int before using `|` on them.
// TODO replace all c.pref.translated checks with `$if !translated` for performance
continue
}
if left_is_ptr && (right is ast.StructInit || !right_is_ptr) && !right_sym.is_number() {
left_name := c.table.type_to_str(left_type_unwrapped)
mut rtype := right_type_unwrapped
if rtype.is_ptr() {
rtype = rtype.deref()
left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
if left_is_ptr {
if !c.inside_unsafe && assign_stmt.op !in [.assign, .decl_assign] {
// ptr op=
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
}
right_is_ptr := right_type.is_ptr() || right_sym.is_pointer()
if !right_is_ptr && assign_stmt.op == .assign && right_type_unwrapped.is_number() {
c.error('cannot assign to `$left`: ' +
c.expected_msg(right_type_unwrapped, left_type_unwrapped), right.position())
}
if (right is ast.StructInit || !right_is_ptr) && !right_sym.is_number() {
left_name := c.table.type_to_str(left_type_unwrapped)
mut rtype := right_type_unwrapped
if rtype.is_ptr() {
rtype = rtype.deref()
}
right_name := c.table.type_to_str(rtype)
c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
}
right_name := c.table.type_to_str(rtype)
c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
}
// Single side check
match assign_stmt.op {
@ -3364,6 +3370,9 @@ pub fn (mut c Checker) ident(mut ident ast.Ident) table.Type {
}
}
if ident.language == .c {
if ident.name == 'C.NULL' {
return table.voidptr_type
}
return table.int_type
}
if c.inside_sql {

View File

@ -0,0 +1,5 @@
vlib/v/checker/tests/ptr_assign.vv:3:5: error: cannot assign to `p`: expected `&int`, not `any_int`
1 | mut v := 43
2 | mut p := &v
3 | p = 4
| ^

View File

@ -0,0 +1,3 @@
mut v := 43
mut p := &v
p = 4

View File

@ -193,7 +193,7 @@ pub fn (mut g JsGen) enter_namespace(name string) {
}
pub fn (mut g JsGen) escape_namespace() {
g.ns = 0
g.ns = &Namespace(0)
g.inside_builtin = false
}
@ -1535,4 +1535,4 @@ fn (mut g JsGen) gen_type_cast_expr(it ast.CastExpr) {
if !is_literal {
g.write(')')
}
}
}

View File

@ -14,3 +14,8 @@ fn JS.f(a &Foo) // TODO: Should this be allowed?
fn C.g(string, ...int)
fn C.h(&int)
fn JS.i(...string)
fn test_null() {
np := C.NULL
assert typeof(np).name == 'voidptr'
}