1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: allow EnumName(number) casts only inside unsafe{} blocks (#15932)

This commit is contained in:
Swastik Baranwal 2022-10-03 01:09:11 +05:30 committed by GitHub
parent 7993f0bf39
commit b584e1df98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 129 additions and 97 deletions

View File

@ -768,7 +768,7 @@ fn (mut app App) next_theme() {
[inline]
fn (mut app App) next_tile_format() {
app.tile_format = TileFormat(int(app.tile_format) + 1)
app.tile_format = unsafe { TileFormat(int(app.tile_format) + 1) }
if app.tile_format == .end_ {
app.tile_format = .normal
}

View File

@ -134,10 +134,10 @@ fn on_event(e &gg.Event, mut app App) {
app.gg.quit()
}
.up {
app.sel = Selection(math.max(0, int(app.sel) - 1))
app.sel = unsafe { Selection(math.max(0, int(app.sel) - 1)) }
}
.down {
app.sel = Selection(math.min(int(Selection.len) - 1, int(app.sel) + 1))
app.sel = unsafe { Selection(math.min(int(Selection.len) - 1, int(app.sel) + 1)) }
}
.left {
match app.sel {

View File

@ -458,7 +458,7 @@ fn frame(mut app App) {
// clear
mut color_action := gfx.ColorAttachmentAction{
action: gfx.Action(C.SG_ACTION_DONTCARE) // C.SG_ACTION_CLEAR)
action: unsafe { gfx.Action(C.SG_ACTION_DONTCARE) } // C.SG_ACTION_CLEAR)
value: gfx.Color{
r: 1.0
g: 1.0

View File

@ -225,7 +225,7 @@ enum WiSiCode {
fn split_int_errno(rc_in u64) (i64, Errno) {
rc := i64(rc_in)
if rc < 0 {
return i64(-1), Errno(-rc)
return i64(-1), unsafe { Errno(-rc) }
}
return rc, Errno.enoerror
}
@ -247,7 +247,7 @@ fn sys_open(filename &byte, flags i64, mode int) (i64, Errno) {
// 3 sys_close
fn sys_close(fd i64) Errno {
return Errno(-i64(sys_call1(3, u64(fd))))
return unsafe { Errno(-i64(sys_call1(3, u64(fd)))) }
}
// 9 sys_mmap
@ -259,7 +259,7 @@ fn sys_mmap(addr &byte, len u64, prot MemProt, flags MapFlags, fildes u64, off u
// 11 sys_munmap
fn sys_munmap(addr voidptr, len u64) Errno {
return Errno(-sys_call2(11, u64(addr), len))
return unsafe { Errno(-sys_call2(11, u64(addr), len)) }
}
// 25 sys_mremap
@ -271,17 +271,17 @@ fn sys_mremap(old_addr voidptr, old_len u64, new_len u64, flags u64) (&byte, Err
// 22 sys_pipe
fn sys_pipe(filedes &int) Errno {
return Errno(sys_call1(22, u64(filedes)))
return unsafe { Errno(sys_call1(22, u64(filedes))) }
}
// 24 sys_sched_yield
fn sys_sched_yield() Errno {
return Errno(sys_call0(24))
return unsafe { Errno(sys_call0(24)) }
}
// 28 sys_madvise
fn sys_madvise(addr voidptr, len u64, advice int) Errno {
return Errno(sys_call3(28, u64(addr), len, u64(advice)))
return unsafe { Errno(sys_call3(28, u64(addr), len, u64(advice))) }
}
// 39 sys_getpid
@ -323,7 +323,9 @@ fn sys_getuid() int {
// 247 sys_waitid
fn sys_waitid(which WiWhich, pid int, infop &int, options int, ru voidptr) Errno {
return Errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru)))
return unsafe {
Errno(sys_call5(247, u64(which), u64(pid), u64(infop), u64(options), u64(ru)))
}
}
fn sys_call0(scn u64) u64 {

View File

@ -6,8 +6,8 @@ fn mm_alloc(size u64) (&byte, Errno) {
// BEGIN CONSTS
// the constants need to be here, since the initialization of other constants,
// which happen before these ones would, require malloc
mem_prot := MemProt(int(MemProt.prot_read) | int(MemProt.prot_write))
map_flags := MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous))
mem_prot := unsafe { MemProt(int(MemProt.prot_read) | int(MemProt.prot_write)) }
map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS
a, e := sys_mmap(&u8(0), size + sizeof(u64), mem_prot, map_flags, -1, 0)
@ -34,8 +34,8 @@ fn system_alloc(_ voidptr, size usize) (voidptr, usize, u32) {
// BEGIN CONSTS
// the constants need to be here, since the initialization of other constants,
// which happen before these ones would, require malloc
mem_prot := MemProt(int(MemProt.prot_read) | int(MemProt.prot_write))
map_flags := MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous))
mem_prot := unsafe { MemProt(int(MemProt.prot_read) | int(MemProt.prot_write)) }
map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS
a, e := sys_mmap(&u8(0), u64(size), mem_prot, map_flags, -1, 0)

View File

@ -151,7 +151,7 @@ pub fn get_str_intp_u32_format(fmt_type StrIntpType, in_width int, in_precision
[manualfree]
fn (data &StrIntpData) process_str_intp_data(mut sb strings.Builder) {
x := data.fmt
typ := StrIntpType(x & 0x1F)
typ := unsafe { StrIntpType(x & 0x1F) }
allign := int((x >> 5) & 0x01)
upper_case := ((x >> 7) & 0x01) > 0
sign := int((x >> 8) & 0x01)

View File

@ -290,12 +290,12 @@ fn gg_event_fn(ce voidptr, user_data voidptr) {
if e.typ == .mouse_down {
bitplace := int(e.mouse_button)
ctx.mbtn_mask |= u8(1 << bitplace)
ctx.mouse_buttons = MouseButtons(ctx.mbtn_mask)
ctx.mouse_buttons = unsafe { MouseButtons(ctx.mbtn_mask) }
}
if e.typ == .mouse_up {
bitplace := int(e.mouse_button)
ctx.mbtn_mask &= ~(u8(1 << bitplace))
ctx.mouse_buttons = MouseButtons(ctx.mbtn_mask)
ctx.mouse_buttons = unsafe { MouseButtons(ctx.mbtn_mask) }
}
if e.typ == .mouse_move && e.mouse_button == .invalid {
if ctx.mbtn_mask & 0x01 > 0 {
@ -314,7 +314,7 @@ fn gg_event_fn(ce voidptr, user_data voidptr) {
ctx.mouse_dy = int(e.mouse_dy / ctx.scale)
ctx.scroll_x = int(e.scroll_x / ctx.scale)
ctx.scroll_y = int(e.scroll_y / ctx.scale)
ctx.key_modifiers = Modifier(e.modifiers)
ctx.key_modifiers = unsafe { Modifier(e.modifiers) }
ctx.key_repeat = e.key_repeat
if e.typ in [.key_down, .key_up] {
key_idx := int(e.key_code) % key_code_max
@ -361,12 +361,12 @@ fn gg_event_fn(ce voidptr, user_data voidptr) {
}
.key_down {
if ctx.config.keydown_fn != unsafe { nil } {
ctx.config.keydown_fn(e.key_code, Modifier(e.modifiers), ctx.config.user_data)
ctx.config.keydown_fn(e.key_code, unsafe { Modifier(e.modifiers) }, ctx.config.user_data)
}
}
.key_up {
if ctx.config.keyup_fn != unsafe { nil } {
ctx.config.keyup_fn(e.key_code, Modifier(e.modifiers), ctx.config.user_data)
ctx.config.keyup_fn(e.key_code, unsafe { Modifier(e.modifiers) }, ctx.config.user_data)
}
}
.char {

View File

@ -28,7 +28,7 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
for i in 0 .. num_fields {
f := unsafe { fields[i] }
match FieldType(f.@type) {
match unsafe { FieldType(f.@type) } {
.type_tiny {
dataptr << unsafe { malloc(1) }
}
@ -57,7 +57,7 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
dataptr << unsafe { malloc(2) }
}
else {
return error('\'${FieldType(f.@type)}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new')
return error('\'${unsafe { FieldType(f.@type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new')
}
}
}
@ -74,14 +74,14 @@ pub fn (db Connection) @select(config orm.SelectConfig, data orm.QueryData, wher
for i, mut mysql_bind in stmt.res {
f := unsafe { fields[i] }
field_types << FieldType(f.@type)
field_types << unsafe { FieldType(f.@type) }
match types[i] {
orm.string {
mysql_bind.buffer_type = C.MYSQL_TYPE_BLOB
mysql_bind.buffer_length = FieldType.type_blob.get_len()
}
orm.time {
match FieldType(f.@type) {
match unsafe { FieldType(f.@type) } {
.type_long {
mysql_bind.buffer_type = C.MYSQL_TYPE_LONG
}

View File

@ -212,7 +212,7 @@ pub fn (mut stmt Stmt) bind(typ int, buffer voidptr, buf_len u32) {
pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&u8, lens []u32, num_fields int) {
for i in 0 .. num_fields {
len := FieldType(unsafe { fields[i].@type }).get_len()
len := unsafe { FieldType(fields[i].@type).get_len() }
stmt.res << C.MYSQL_BIND{
buffer_type: unsafe { fields[i].@type }
buffer: dataptr[i]

View File

@ -57,7 +57,7 @@ fn temp_unix() ?Addr {
}
pub fn (a Addr) family() AddrFamily {
return AddrFamily(a.f)
return unsafe { AddrFamily(a.f) }
}
const (
@ -206,7 +206,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ?[]Addr {
mut addresses := []Addr{}
for result := unsafe { results }; !isnil(result); result = result.ai_next {
match AddrFamily(result.ai_family) {
match unsafe { AddrFamily(result.ai_family) } {
.ip {
new_addr := Addr{
addr: AddrData{
@ -239,7 +239,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ?[]Addr {
}
fn (a Addr) str() string {
match AddrFamily(a.f) {
match unsafe { AddrFamily(a.f) } {
.ip {
unsafe {
return a.addr.Ip.str()

View File

@ -158,7 +158,7 @@ fn (mut c Client) expect_reply(expected ReplyCode) ? {
if str.len >= 3 {
status := str[..3].int()
if ReplyCode(status) != expected {
if unsafe { ReplyCode(status) } != expected {
return error('Received unexpected status code $status, expecting $expected')
}
} else {

View File

@ -228,7 +228,7 @@ pub fn (mut ws Client) parse_frame_header() ?Frame {
frame.rsv1 = (buffer[0] & 0x40) == 0x40
frame.rsv2 = (buffer[0] & 0x20) == 0x20
frame.rsv3 = (buffer[0] & 0x10) == 0x10
frame.opcode = OPCode(int(buffer[0] & 0x7F))
frame.opcode = unsafe { OPCode(int(buffer[0] & 0x7F)) }
frame.has_mask = (buffer[1] & 0x80) == 0x80
frame.payload_len = buffer[1] & 0x7F
// if has mask set the byte postition where mask ends

View File

@ -2,7 +2,7 @@ module gfx
pub fn create_clear_pass(r f32, g f32, b f32, a f32) PassAction {
mut color_action := ColorAttachmentAction{
action: Action(C.SG_ACTION_CLEAR)
action: unsafe { Action(C.SG_ACTION_CLEAR) }
value: Color{
r: r
g: g

View File

@ -20,12 +20,12 @@ pub fn shutdown() {
[inline]
pub fn error() SglError {
return SglError(int(C.sgl_error()))
return unsafe { SglError(int(C.sgl_error())) }
}
[inline]
pub fn context_error(ctx Context) SglError {
return SglError(int(C.sgl_context_error(ctx)))
return unsafe { SglError(int(C.sgl_context_error(ctx))) }
}
[inline]

View File

@ -289,7 +289,7 @@ fn single_char(buf string) &Event {
mut event := &Event{
typ: .key_down
ascii: ch
code: KeyCode(ch)
code: unsafe { KeyCode(ch) }
utf8: ch.ascii_str()
}
@ -305,7 +305,7 @@ fn single_char(buf string) &Event {
typ: event.typ
ascii: event.ascii
utf8: event.utf8
code: KeyCode(96 | ch)
code: unsafe { KeyCode(96 | ch) }
modifiers: .ctrl
}
}
@ -314,7 +314,7 @@ fn single_char(buf string) &Event {
typ: event.typ
ascii: event.ascii
utf8: event.utf8
code: KeyCode(32 | ch)
code: unsafe { KeyCode(32 | ch) }
modifiers: .shift
}
}
@ -330,7 +330,7 @@ fn multi_char(buf string) (&Event, int) {
mut event := &Event{
typ: .key_down
ascii: ch
code: KeyCode(ch)
code: unsafe { KeyCode(ch) }
utf8: buf
}
@ -346,7 +346,7 @@ fn multi_char(buf string) (&Event, int) {
typ: event.typ
ascii: event.ascii
utf8: event.utf8
code: KeyCode(96 | ch)
code: unsafe { KeyCode(96 | ch) }
modifiers: .ctrl
}
}
@ -355,7 +355,7 @@ fn multi_char(buf string) (&Event, int) {
typ: event.typ
ascii: event.ascii
utf8: event.utf8
code: KeyCode(32 | ch)
code: unsafe { KeyCode(32 | ch) }
modifiers: .shift
}
}
@ -447,7 +447,7 @@ fn escape_sequence(buf_ string) (&Event, int) {
match typ {
0...31 {
last := buf[buf.len - 1]
button := if lo < 3 { MouseButton(lo + 1) } else { MouseButton.unknown }
button := if lo < 3 { unsafe { MouseButton(lo + 1) } } else { MouseButton.unknown }
event := if last == `m` || lo == 3 {
EventType.mouse_up
} else {
@ -465,7 +465,7 @@ fn escape_sequence(buf_ string) (&Event, int) {
}
32...63 {
button, event := if lo < 3 {
MouseButton(lo + 1), EventType.mouse_drag
unsafe { MouseButton(lo + 1), EventType.mouse_drag }
} else {
MouseButton.unknown, EventType.mouse_move
}

View File

@ -31,7 +31,7 @@ fn (mut e Employee) from_toml(any toml.Any) {
e.age = mp['age'] or { toml.Any(0) }.int()
e.salary = mp['salary'] or { toml.Any(0) }.f32()
e.is_human = mp['is_human'] or { toml.Any(false) }.bool()
e.title = JobTitle(mp['title'] or { toml.Any(0) }.int())
e.title = unsafe { JobTitle(mp['title'] or { toml.Any(0) }.int()) }
}
fn test_encode_and_decode() {

View File

@ -143,7 +143,7 @@ pub fn (t Type) atomic_typename() string {
}
pub fn sharetype_from_flags(is_shared bool, is_atomic bool) ShareType {
return ShareType(int(u32(is_atomic) << 1) | int(is_shared))
return unsafe { ShareType(int(u32(is_atomic) << 1) | int(is_shared)) }
}
pub fn (t Type) share() ShareType {

View File

@ -2542,6 +2542,10 @@ pub fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
c.error('cannot cast `$ft` to rune, use `${snexpr}.runes()` instead.', node.pos)
}
if to_sym.kind == .enum_ && !(c.inside_unsafe || c.file.is_translated) && from_sym.is_int() {
c.error('casting numbers to enums, should be done inside `unsafe{}` blocks', node.pos)
}
if to_type == ast.string_type {
if from_type in [ast.u8_type, ast.bool_type] {
snexpr := node.expr.str()

View File

@ -0,0 +1,6 @@
vlib/v/checker/tests/casting_numbers_to_enums_outside_unsafe_err.vv:7:6: error: casting numbers to enums, should be done inside `unsafe{}` blocks
5 | }
6 |
7 | a := Abc(1)
| ~~~~~~
8 | println(a)

View File

@ -0,0 +1,8 @@
enum Abc {
a
b
c
}
a := Abc(1)
println(a)

View File

@ -1,27 +1,27 @@
vlib/v/checker/tests/enum_cast.vv:9:13: warning: 12 does not represent a value of enum Color
7 | println(Color(0))
8 | println(Color(10))
9 | println(Color(12))
| ~~~~~~~~~
10 | println(Color(-10))
11 |
vlib/v/checker/tests/enum_cast.vv:10:13: warning: -10 does not represent a value of enum Color
8 | println(Color(10))
9 | println(Color(12))
10 | println(Color(-10))
| ~~~~~~~~~~
11 |
12 | println(Permissions(0b101))
vlib/v/checker/tests/enum_cast.vv:13:13: warning: 10 does not represent a value of enum Permissions
11 |
12 | println(Permissions(0b101))
13 | println(Permissions(0b1010))
| ~~~~~~~~~~~~~~~~~~~
14 | println(Permissions(-1))
15 | }
vlib/v/checker/tests/enum_cast.vv:14:13: warning: -1 does not represent a value of enum Permissions
12 | println(Permissions(0b101))
13 | println(Permissions(0b1010))
14 | println(Permissions(-1))
| ~~~~~~~~~~~~~~~
15 | }
vlib/v/checker/tests/enum_cast.vv:17:19: warning: 12 does not represent a value of enum Color
15 | println(unsafe { Color(0) })
16 | println(unsafe { Color(10) })
17 | println(unsafe { Color(12) })
| ~~~~~~~~~
18 | println(unsafe { Color(-10) })
19 |
vlib/v/checker/tests/enum_cast.vv:18:19: warning: -10 does not represent a value of enum Color
16 | println(unsafe { Color(10) })
17 | println(unsafe { Color(12) })
18 | println(unsafe { Color(-10) })
| ~~~~~~~~~~
19 |
20 | println(unsafe { Permissions(0b101) })
vlib/v/checker/tests/enum_cast.vv:21:19: warning: 10 does not represent a value of enum Permissions
19 |
20 | println(unsafe { Permissions(0b101) })
21 | println(unsafe { Permissions(0b1010) })
| ~~~~~~~~~~~~~~~~~~~
22 | println(unsafe { Permissions(-1) })
23 | }
vlib/v/checker/tests/enum_cast.vv:22:19: warning: -1 does not represent a value of enum Permissions
20 | println(unsafe { Permissions(0b101) })
21 | println(unsafe { Permissions(0b1010) })
22 | println(unsafe { Permissions(-1) })
| ~~~~~~~~~~~~~~~
23 | }

View File

@ -1,15 +1,23 @@
enum Color { red green = 10 blue }
enum Color {
red
green = 10
blue
}
[flag]
enum Permissions { read write execute }
enum Permissions {
read
write
execute
}
fn main() {
println(Color(0))
println(Color(10))
println(Color(12))
println(Color(-10))
println(unsafe { Color(0) })
println(unsafe { Color(10) })
println(unsafe { Color(12) })
println(unsafe { Color(-10) })
println(Permissions(0b101))
println(Permissions(0b1010))
println(Permissions(-1))
println(unsafe { Permissions(0b101) })
println(unsafe { Permissions(0b1010) })
println(unsafe { Permissions(-1) })
}

View File

@ -514,7 +514,11 @@ pub fn generate(input_path string, pub_only bool, with_comments bool, platform P
doc.pub_only = pub_only
doc.with_comments = with_comments
doc.filter_symbol_names = filter_symbol_names.filter(it.len != 0)
doc.prefs.os = if platform == .auto { pref.get_host_os() } else { pref.OS(int(platform)) }
doc.prefs.os = if platform == .auto {
pref.get_host_os()
} else {
unsafe { pref.OS(int(platform)) }
}
doc.generate()?
return doc
}

View File

@ -61,11 +61,11 @@ fn value_test() {
assert int(Value.c) == 15
assert int(Value.d) == 16
assert int(Value.e) == 3
assert Value.a == Value(0)
assert Value.b == Value(1)
assert Value.c == Value(15)
assert Value.d == Value(16)
assert Value.e == Value(3)
assert Value.a == unsafe { Value(0) }
assert Value.b == unsafe { Value(1) }
assert Value.c == unsafe { Value(15) }
assert Value.d == unsafe { Value(16) }
assert Value.e == unsafe { Value(3) }
}
fn main() {

View File

@ -292,7 +292,7 @@ fn (mut p Parser) partial_assign_stmt(left []ast.Expr, left_comments []ast.Comme
if p.scope.known_var(lx.name) {
return p.error_with_pos('redefinition of `$lx.name`', lx.pos)
}
mut share := ast.ShareType(0)
mut share := unsafe { ast.ShareType(0) }
if mut lx.info is ast.IdentVar {
share = lx.info.share
if lx.info.is_static {

View File

@ -994,7 +994,7 @@ pub fn get_host_arch() Arch {
if C.__V_architecture <= int(Arch._auto) || C.__V_architecture >= int(Arch._max) {
return Arch.amd64
}
return Arch(C.__V_architecture)
return unsafe { Arch(C.__V_architecture) }
}
fn (mut prefs Preferences) parse_define(define string) {

View File

@ -668,7 +668,7 @@ fn (mut s Scanner) text_scan() token.Token {
kind := token.scanner_matcher.find(name)
// '$type' '$struct'... will be recognized as ident (not keyword token)
if kind != -1 && !(s.is_inter_start && next_char == s.quote) {
return s.new_token(token.Kind(kind), name, name.len)
return s.new_token(unsafe { token.Kind(kind) }, name, name.len)
}
// 'asdf $b' => "b" is the last name in the string, dont start parsing string
// at the next ', skip it

View File

@ -10,7 +10,7 @@ mut:
}
fn test_enum_first_value() {
assert MyEnum.first == MyEnum(20)
assert MyEnum.first == unsafe { MyEnum(20) }
}
fn test_enum_default_value() {

View File

@ -82,10 +82,10 @@ enum Foo {
fn test_nums() {
foo := Foo.a
assert foo == Foo(1)
assert Foo.c == Foo(3)
assert foo == unsafe { Foo(1) }
assert Foo.c == unsafe { Foo(3) }
d := Foo.d
assert d == Foo(-10)
assert d == unsafe { Foo(-10) }
}
/*

View File

@ -197,7 +197,7 @@ fn build_keys() map[string]Kind {
mut res := map[string]Kind{}
for t in int(Kind.keyword_beg) + 1 .. int(Kind.keyword_end) {
key := token.token_str[t]
res[key] = Kind(t)
res[key] = unsafe { Kind(t) }
}
return res
}
@ -326,7 +326,7 @@ fn build_token_str() []string {
$if debug_build_token_str ? {
for k, v in s {
if v == '' {
eprintln('>>> ${@MOD}.${@METHOD} missing k: $k | .${kind_to_string(Kind(k))}')
eprintln('>>> ${@MOD}.${@METHOD} missing k: $k | .${kind_to_string(unsafe { Kind(k) })}')
}
}
}

View File

@ -39,7 +39,7 @@ fn (mut e Employee) from_json(any json2.Any) {
e.name = mp['name'] or { json2.Any('') }.str()
e.age = mp['age'] or { json2.Any(0) }.int()
e.salary = mp['salary'] or { json2.Any(0) }.f32()
e.title = JobTitle(mp['title'] or { json2.Any(0) }.int())
e.title = unsafe { JobTitle(mp['title'] or { json2.Any(0) }.int()) }
}
fn test_simple() {

View File

@ -298,7 +298,7 @@ fn (mut s Scanner) scan() Token {
return s.invalid_token()
} else if s.text[s.pos] in json2.char_list {
chr := s.text[s.pos]
tok := s.tokenize([]u8{}, TokenKind(int(chr)))
tok := s.tokenize([]u8{}, unsafe { TokenKind(int(chr)) })
s.move()
return tok
} else if s.text[s.pos] == `"` {