From 0ba5544446b199a44ea2983e00dbb8109ce36f48 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 7 Nov 2020 21:19:46 +0200 Subject: [PATCH] checker: add a check for `ptr = Abc{}` --- vlib/os/os_c.v | 38 +++++++++++++------ vlib/v/checker/checker.v | 14 ++++++- .../struct_assigned_to_pointer_to_struct.out | 13 +++++++ .../struct_assigned_to_pointer_to_struct.vv | 7 ++++ 4 files changed, 58 insertions(+), 14 deletions(-) create mode 100644 vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.out create mode 100644 vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv diff --git a/vlib/os/os_c.v b/vlib/os/os_c.v index dd131cf43e..8f76470148 100644 --- a/vlib/os/os_c.v +++ b/vlib/os/os_c.v @@ -2,27 +2,41 @@ module os #include // #include #include +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.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 { st_size int st_mode u32 st_mtime int } -struct C.DIR {} +struct C.DIR { +} struct C.sigaction { mut: diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 6966eb6102..e4acc862d1 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2080,8 +2080,9 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { right_type_unwrapped := c.unwrap_generic(right_type) left_sym := c.table.get_type_symbol(left_type_unwrapped) right_sym := c.table.get_type_symbol(right_type_unwrapped) - if (left_type.is_ptr() || left_sym.is_pointer()) && - assign_stmt.op !in [.assign, .decl_assign] && !c.inside_unsafe { + 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) } @@ -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 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 match assign_stmt.op { .assign {} // No need to do single side check for =. But here put it first for speed. diff --git a/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.out b/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.out new file mode 100644 index 0000000000..734ec37fce --- /dev/null +++ b/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.out @@ -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 | } diff --git a/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv b/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv new file mode 100644 index 0000000000..ec9573cc4f --- /dev/null +++ b/vlib/v/checker/tests/struct_assigned_to_pointer_to_struct.vv @@ -0,0 +1,7 @@ +struct Foo { x int } + +fn main() { + mut f := &Foo{ 10 } + f = { x: 223344 } + f = Foo{ x: 20 } +}