checker: add a check for `ptr = Abc{}`

pull/6776/head
Delyan Angelov 2020-11-07 21:19:46 +02:00
parent 931882d720
commit 0ba5544446
4 changed files with 58 additions and 14 deletions

View File

@ -2,27 +2,41 @@ module os
#include <sys/stat.h> // #include <signal.h> #include <sys/stat.h> // #include <signal.h>
#include <errno.h> #include <errno.h>
struct C.dirent {
d_name [256]char
}
fn C.readdir(voidptr) &C.dirent
fn C.readdir(voidptr) C.dirent
fn C.getpid() int fn C.getpid() int
fn C.readlink() int
fn C.getline(voidptr, voidptr, voidptr) int
fn C.ftell(fp voidptr) int
fn C.sigaction(int, voidptr, int)
fn C.open(charptr, int, int) int
fn C.fdopen(int, string) voidptr
fn C.CopyFile(&u32, &u32, int) int
fn C.fork() int
fn C.wait() int
//fn C.proc_pidpath(int, byteptr, int) int
fn C.readlink() int
fn C.getline(voidptr, voidptr, voidptr) int
fn C.ftell(fp voidptr) int
fn C.sigaction(int, voidptr, int)
fn C.open(charptr, int, int) int
fn C.fdopen(int, string) voidptr
fn C.CopyFile(&u32, &u32, int) int
fn C.fork() int
fn C.wait() int
// fn C.proc_pidpath(int, byteptr, int) int
struct C.stat { struct C.stat {
st_size int st_size int
st_mode u32 st_mode u32
st_mtime int st_mtime int
} }
struct C.DIR {} struct C.DIR {
}
struct C.sigaction { struct C.sigaction {
mut: mut:

View File

@ -2080,8 +2080,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
right_type_unwrapped := c.unwrap_generic(right_type) right_type_unwrapped := c.unwrap_generic(right_type)
left_sym := c.table.get_type_symbol(left_type_unwrapped) left_sym := c.table.get_type_symbol(left_type_unwrapped)
right_sym := c.table.get_type_symbol(right_type_unwrapped) right_sym := c.table.get_type_symbol(right_type_unwrapped)
if (left_type.is_ptr() || left_sym.is_pointer()) && left_is_ptr := left_type.is_ptr() || left_sym.is_pointer()
assign_stmt.op !in [.assign, .decl_assign] && !c.inside_unsafe { 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= // ptr op=
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos) c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos)
} }
@ -2090,6 +2091,15 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) {
// TODO replace all c.pref.translated checks with `$if !translated` for performance // TODO replace all c.pref.translated checks with `$if !translated` for performance
continue 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()
}
right_name := c.table.type_to_str(rtype)
c.error('mismatched types `$left_name` and `$right_name`', assign_stmt.pos)
}
// Single side check // Single side check
match assign_stmt.op { match assign_stmt.op {
.assign {} // No need to do single side check for =. But here put it first for speed. .assign {} // No need to do single side check for =. But here put it first for speed.

View File

@ -0,0 +1,13 @@
vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv:5:4: error: mismatched types `&Foo` and `Foo`
3 | fn main() {
4 | mut f := &Foo{ 10 }
5 | f = { x: 223344 }
| ^
6 | f = Foo{ x: 20 }
7 | }
vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv:6:4: error: mismatched types `&Foo` and `Foo`
4 | mut f := &Foo{ 10 }
5 | f = { x: 223344 }
6 | f = Foo{ x: 20 }
| ^
7 | }

View File

@ -0,0 +1,7 @@
struct Foo { x int }
fn main() {
mut f := &Foo{ 10 }
f = { x: 223344 }
f = Foo{ x: 20 }
}