Skip to content

Commit 071ab6c

Browse files
authored
checker, cgen: fix non-voidptr to voidptr on -cstrict + notice about such usage (fix #24139) (#24143)
1 parent 52b5c32 commit 071ab6c

7 files changed

Lines changed: 79 additions & 8 deletions

File tree

‎vlib/os/file.c.v‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ pub fn create(path string) !File {
187187
pub fn stdin() File {
188188
return File{
189189
fd: 0
190-
cfile: C.stdin
190+
cfile: voidptr(C.stdin)
191191
is_opened: true
192192
}
193193
}
@@ -196,7 +196,7 @@ pub fn stdin() File {
196196
pub fn stdout() File {
197197
return File{
198198
fd: 1
199-
cfile: C.stdout
199+
cfile: voidptr(C.stdout)
200200
is_opened: true
201201
}
202202
}
@@ -205,7 +205,7 @@ pub fn stdout() File {
205205
pub fn stderr() File {
206206
return File{
207207
fd: 2
208-
cfile: C.stderr
208+
cfile: voidptr(C.stderr)
209209
is_opened: true
210210
}
211211
}

‎vlib/v/checker/fn.v‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -863,6 +863,7 @@ fn (mut c Checker) needs_unwrap_generic_type(typ ast.Type) bool {
863863
fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.Type {
864864
is_va_arg := node.name == 'C.va_arg'
865865
is_json_decode := node.name == 'json.decode'
866+
is_json_encode := node.name == 'json.encode'
866867
mut fn_name := node.name
867868
if node.is_static_method {
868869
// resolve static call T.name()
@@ -1780,6 +1781,10 @@ fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool) ast.
17801781
}
17811782
}
17821783
}
1784+
if is_json_encode {
1785+
// json.encode param is set voidptr, we should bound the proper type here
1786+
node.expected_arg_types = [node.args[0].typ]
1787+
}
17831788
if func.generic_names.len != node.concrete_types.len {
17841789
// no type arguments given in call, attempt implicit instantiation
17851790
c.infer_fn_generic_types(func, mut node)

‎vlib/v/checker/struct.v‎

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,16 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
133133
}
134134
}
135135

136+
if c.table.final_sym(field.typ).kind == .voidptr
137+
&& field.default_expr_typ !in [ast.nil_type, ast.voidptr_type, ast.byteptr_type]
138+
&& !field.default_expr_typ.is_ptr()
139+
&& (field.default_expr !is ast.IntegerLiteral
140+
|| (field.default_expr is ast.IntegerLiteral
141+
&& field.default_expr.val.int() != 0)) {
142+
c.note('voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(${field.default_expr.str()}) })',
143+
field.default_expr.pos())
144+
}
145+
136146
// disallow map `mut a = b`
137147
field_sym := c.table.sym(field.typ)
138148
expr_sym := c.table.sym(field.default_expr_typ)
@@ -716,10 +726,17 @@ fn (mut c Checker) struct_init(mut node ast.StructInit, is_field_zero_struct_ini
716726
if exp_type_is_option && got_type.is_ptr() && !exp_type.is_ptr() {
717727
c.error('cannot assign a pointer to option struct field', init_field.pos)
718728
}
719-
if exp_type_sym.kind == .voidptr && got_type_sym.kind == .struct
720-
&& !got_type.is_ptr() {
721-
c.error('allocate `${got_type_sym.name}` on the heap for use in other functions',
722-
init_field.pos)
729+
if exp_type_sym.kind == .voidptr {
730+
if got_type_sym.kind == .struct && !got_type.is_ptr() {
731+
c.error('allocate `${got_type_sym.name}` on the heap for use in other functions',
732+
init_field.pos)
733+
} else if got_type !in [ast.nil_type, ast.voidptr_type, ast.byteptr_type]
734+
&& !got_type.is_ptr() && (init_field.expr !is ast.IntegerLiteral
735+
|| (init_field.expr is ast.IntegerLiteral
736+
&& init_field.expr.val.int() != 0)) {
737+
c.note('voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(${init_field.expr.str()}) })',
738+
init_field.expr.pos())
739+
}
723740
}
724741
// disallow `mut a: b`, when b is const map
725742
if exp_type_sym.kind == .map && got_type_sym.kind == .map && !got_type.is_ptr()
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
vlib/v/checker/tests/struct_void_field_err.vv:5:16: notice: voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(1) })
2+
3 | struct Foo {
3+
4 | mut:
4+
5 | bar voidptr = 1
5+
| ^
6+
6 | }
7+
7 |
8+
vlib/v/checker/tests/struct_void_field_err.vv:11:8: notice: voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(n) })
9+
9 | n := 1
10+
10 | _ := Foo{
11+
11 | bar: n
12+
| ^
13+
12 | }
14+
13 | _ := Foo{
15+
vlib/v/checker/tests/struct_void_field_err.vv:17:8: notice: voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(1) })
16+
15 | }
17+
16 | _ := Foo{
18+
17 | bar: 1
19+
| ^
20+
18 | }
21+
19 | }
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module main
2+
3+
struct Foo {
4+
mut:
5+
bar voidptr = 1
6+
}
7+
8+
fn main() {
9+
n := 1
10+
_ := Foo{
11+
bar: n
12+
}
13+
_ := Foo{
14+
bar: 0
15+
}
16+
_ := Foo{
17+
bar: 1
18+
}
19+
}

‎vlib/v/checker/tests/struct_voidptr_field_init_err.out‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
vlib/v/checker/tests/struct_voidptr_field_init_err.vv:7:12: notice: voidptr variables may only be assigned voidptr values (e.g. unsafe { voidptr(get()) })
2+
5 | fn main() {
3+
6 | println(Example{
4+
7 | example: get()
5+
| ~~~~~
6+
8 | })
7+
9 | }
18
vlib/v/checker/tests/struct_voidptr_field_init_err.vv:7:3: error: cannot assign to field `example`: expected a pointer `voidptr`, but got `string`
29
5 | fn main() {
310
6 | println(Example{

‎vlib/v/gen/c/cgen.v‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3092,7 +3092,9 @@ fn (mut g Gen) expr_with_cast(expr ast.Expr, got_type_raw ast.Type, expected_typ
30923092
return
30933093
}
30943094
}
3095-
if exp_sym.kind == .function && !expected_type.has_option_or_result() {
3095+
if (exp_sym.kind == .function && !expected_type.has_option_or_result())
3096+
|| (g.inside_struct_init && expected_type == ast.voidptr_type
3097+
&& expected_type != got_type_raw) {
30963098
g.write('(voidptr)')
30973099
}
30983100
// no cast

0 commit comments

Comments
 (0)