diff --git a/vlib/strconv/atof.v b/vlib/strconv/atof.v index 5df6bc5eac..8a48775ff9 100644 --- a/vlib/strconv/atof.v +++ b/vlib/strconv/atof.v @@ -522,7 +522,6 @@ pub fn atof64(s string) f64 { res_parsing,pn = parser(s + ' ') // TODO: need an extra char for now // println(pn) - unsafe { match res_parsing { parser_ok { res.u = converter(mut pn) @@ -542,6 +541,5 @@ pub fn atof64(s string) f64 { else { } } - return res.f - } + return unsafe {res.f} } diff --git a/vlib/strconv/atofq.v b/vlib/strconv/atofq.v index 70e84c0359..d8c25623c5 100644 --- a/vlib/strconv/atofq.v +++ b/vlib/strconv/atofq.v @@ -37,7 +37,6 @@ pub fn atof_quick(s string) f64 { i++ } } - unsafe { // infinite if s[i] == `i` && i + 2 < s.len && s[i + 1] == `n` && s[i + 2] == `f` { if sign > 0.0 { @@ -46,7 +45,7 @@ pub fn atof_quick(s string) f64 { else { f.u = double_minus_infinity } - return f.f + return unsafe {f.f} } // skip zeros for i < s.len && s[i] == `0` { @@ -59,7 +58,7 @@ pub fn atof_quick(s string) f64 { else { f.u = double_minus_zero } - return f.f + return unsafe {f.f} } } // integer part @@ -110,11 +109,11 @@ pub fn atof_quick(s string) f64 { else { f.u = double_minus_infinity } - return f.f + return unsafe {f.f} } tmp_mul := Float64u{u: pos_exp[exp]} // C.printf("exp: %d [0x%016llx] %f,",exp,pos_exp[exp],tmp_mul) - f.f = f.f * tmp_mul.f + f.f = unsafe {f.f * tmp_mul.f} } else { if exp > neg_exp.len { @@ -124,16 +123,17 @@ pub fn atof_quick(s string) f64 { else { f.u = double_minus_zero } - return f.f + return unsafe {f.f} } tmp_mul := Float64u{u: neg_exp[exp]} // C.printf("exp: %d [0x%016llx] %f,",exp,pos_exp[exp],tmp_mul) - f.f = f.f * tmp_mul.f + f.f = unsafe {f.f * tmp_mul.f} } } - f.f = f.f * sign - return f.f + unsafe { + f.f = f.f * sign + return f.f } } diff --git a/vlib/strconv/f32_f64_to_string_test.v b/vlib/strconv/f32_f64_to_string_test.v index f7fd7ac734..f86be0ff29 100644 --- a/vlib/strconv/f32_f64_to_string_test.v +++ b/vlib/strconv/f32_f64_to_string_test.v @@ -22,14 +22,14 @@ fn f64_from_bits1(b u64) f64 { mut x := Ufloat64{} x.b = b //C.printf("bin: %016llx\n",x.f) - return x.f + return unsafe {x.f} } fn f32_from_bits1(b u32) f32 { mut x := Ufloat32{} x.b = b //C.printf("bin: %08x\n",x.f) - return x.f + return unsafe {x.f} } fn test_float_to_str() { diff --git a/vlib/strconv/f32_str.v b/vlib/strconv/f32_str.v index b6409cbf10..e377bdd472 100644 --- a/vlib/strconv/f32_str.v +++ b/vlib/strconv/f32_str.v @@ -321,7 +321,7 @@ pub fn f32_to_decimal(mant u32, exp u32) Dec32 { // f32_to_str return a string in scientific notation with max n_digit after the dot pub fn f32_to_str(f f32, n_digit int) string { mut u1 := Uf32{} - unsafe { u1.f = f } + u1.f = f u := unsafe {u1.u} neg := (u>>(mantbits32+expbits32)) != 0 @@ -348,7 +348,7 @@ pub fn f32_to_str(f f32, n_digit int) string { // f32_to_str return a string in scientific notation with max n_digit after the dot pub fn f32_to_str_pad(f f32, n_digit int) string { mut u1 := Uf32{} - unsafe { u1.f = f } + u1.f = f u := unsafe {u1.u} neg := (u>>(mantbits32+expbits32)) != 0 diff --git a/vlib/strconv/f64_str.v b/vlib/strconv/f64_str.v index 39f254a615..9c0cc8d1aa 100644 --- a/vlib/strconv/f64_str.v +++ b/vlib/strconv/f64_str.v @@ -370,7 +370,7 @@ fn f64_to_decimal(mant u64, exp u64) Dec64 { // f64_to_str return a string in scientific notation with max n_digit after the dot pub fn f64_to_str(f f64, n_digit int) string { mut u1 := Uf64{} - unsafe { u1.f = f } + u1.f = f u := unsafe {u1.u} neg := (u>>(mantbits64+expbits64)) != 0 @@ -395,7 +395,7 @@ pub fn f64_to_str(f f64, n_digit int) string { // f64_to_str return a string in scientific notation with max n_digit after the dot pub fn f64_to_str_pad(f f64, n_digit int) string { mut u1 := Uf64{} - unsafe { u1.f = f } + u1.f = f u := unsafe {u1.u} neg := (u>>(mantbits64+expbits64)) != 0 diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 2ece699281..c704a6383d 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -108,6 +108,7 @@ pub: field_name string is_mut bool // is used for the case `if mut ident.selector is MyType {`, it indicates if the root ident is mutable mut_pos token.Position + next_token token.Kind pub mut: expr_type table.Type // type of `Foo` in `Foo.bar` typ table.Type // type of the entire thing (`Foo.bar`) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 810b4bb4ad..274dcdd99c 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1062,9 +1062,6 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) { // No automatic lock for struct access explicit_lock_needed = true } - if struct_info.is_union && !c.inside_unsafe { - c.warn('accessing union fields requires `unsafe`', expr.pos) - } } .array, .string { // This should only happen in `builtin` @@ -2028,6 +2025,7 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T has_field = true field = f } else { + // look for embedded field if sym.info is table.Struct { mut found_fields := []table.Field{} mut embed_of_found_fields := []table.Type{} @@ -2050,6 +2048,14 @@ pub fn (mut c Checker) selector_expr(mut selector_expr ast.SelectorExpr) table.T unknown_field_msg = err } } + if !c.inside_unsafe { + if sym.info is table.Struct { + if sym.info.is_union && selector_expr.next_token !in token.assign_tokens { + c.warn('reading a union field (or its address) requires `unsafe`', + selector_expr.pos) + } + } + } } if has_field { if sym.mod != c.mod && !field.is_pub && sym.language != .c { diff --git a/vlib/v/checker/tests/union_unsafe_fields.out b/vlib/v/checker/tests/union_unsafe_fields.out new file mode 100644 index 0000000000..be40d1bcc3 --- /dev/null +++ b/vlib/v/checker/tests/union_unsafe_fields.out @@ -0,0 +1,13 @@ +vlib/v/checker/tests/union_unsafe_fields.vv:10:9: error: reading a union field (or its address) requires `unsafe` + 8 | mut u := Uf32{u: 3} + 9 | u.f = 3.3 // ok + 10 | _ := u.u + | ^ + 11 | return &u.f + 12 | } +vlib/v/checker/tests/union_unsafe_fields.vv:11:12: error: reading a union field (or its address) requires `unsafe` + 9 | u.f = 3.3 // ok + 10 | _ := u.u + 11 | return &u.f + | ^ + 12 | } diff --git a/vlib/v/checker/tests/union_unsafe_fields.vv b/vlib/v/checker/tests/union_unsafe_fields.vv new file mode 100644 index 0000000000..6a1bc0f8db --- /dev/null +++ b/vlib/v/checker/tests/union_unsafe_fields.vv @@ -0,0 +1,12 @@ +union Uf32 { +mut: + f f32 + u u32 +} + +fn f() f32 { + mut u := Uf32{u: 3} + u.f = 3.3 // ok + _ := u.u + return &u.f +} diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index acbf90d167..95b8de5b22 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -1528,13 +1528,12 @@ fn (mut p Parser) dot_expr(left ast.Expr) ast.Expr { is_mut: is_mut mut_pos: mut_pos scope: p.scope + next_token: p.tok.kind } - mut node := ast.Expr{} - node = sel_expr if is_filter { p.close_scope() } - return node + return sel_expr } // `.green`