checker: fix warning & allow assigning to a union field without unsafe (#7970)

pull/7748/head^2
Nick Treleaven 2021-01-09 00:32:33 +00:00 committed by GitHub
parent 8d3069f643
commit 141b0cb882
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 53 additions and 24 deletions

View File

@ -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}
}

View File

@ -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
}
}

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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`)

View File

@ -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 {

View File

@ -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 | }

View File

@ -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
}

View File

@ -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`