checker: allow ptr++/ptr-- in unsafe{}, for any kind of pointer, except voidptr
parent
84de4622a4
commit
75af639721
|
@ -4680,15 +4680,16 @@ fn (c &Checker) has_return(stmts []ast.Stmt) ?bool {
|
||||||
pub fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) table.Type {
|
pub fn (mut c Checker) postfix_expr(mut node ast.PostfixExpr) table.Type {
|
||||||
typ := c.expr(node.expr)
|
typ := c.expr(node.expr)
|
||||||
typ_sym := c.table.get_type_symbol(typ)
|
typ_sym := c.table.get_type_symbol(typ)
|
||||||
if !typ_sym.is_number() && typ_sym.kind !in [.byteptr, .charptr] {
|
is_non_void_pointer := (typ.is_ptr() || typ.is_pointer()) && typ_sym.kind != .voidptr
|
||||||
|
if !c.inside_unsafe && is_non_void_pointer {
|
||||||
|
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
||||||
|
}
|
||||||
|
if !(typ_sym.is_number() || (c.inside_unsafe && is_non_void_pointer)) {
|
||||||
c.error('invalid operation: $node.op.str() (non-numeric type `$typ_sym.name`)',
|
c.error('invalid operation: $node.op.str() (non-numeric type `$typ_sym.name`)',
|
||||||
node.pos)
|
node.pos)
|
||||||
} else {
|
} else {
|
||||||
node.auto_locked, _ = c.fail_if_immutable(node.expr)
|
node.auto_locked, _ = c.fail_if_immutable(node.expr)
|
||||||
}
|
}
|
||||||
if !c.inside_unsafe && (typ.is_ptr() || typ_sym.is_pointer()) {
|
|
||||||
c.warn('pointer arithmetic is only allowed in `unsafe` blocks', node.pos)
|
|
||||||
}
|
|
||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ pub fn find_index_entry_by_path(start voidptr, path string) &EmbedFileIndexEntry
|
||||||
mut x := &EmbedFileIndexEntry(start)
|
mut x := &EmbedFileIndexEntry(start)
|
||||||
for !(x.path == path || isnil(x.data)) {
|
for !(x.path == path || isnil(x.data)) {
|
||||||
unsafe {
|
unsafe {
|
||||||
x = &EmbedFileIndexEntry(u64(x) + sizeof(EmbedFileIndexEntry))
|
x++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$if debug_embed_file_in_prod ? {
|
$if debug_embed_file_in_prod ? {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
fn test_ptr_arithmetic(){
|
fn test_ptr_arithmetic() {
|
||||||
unsafe {
|
unsafe {
|
||||||
// Do NOT move this outside unsafe{}.
|
// Do NOT move this outside unsafe{}.
|
||||||
// It causes too much churn in CI when new checks are implemented.
|
// It causes too much churn in CI when new checks are implemented.
|
||||||
|
@ -28,7 +28,43 @@ fn test_ptr_arithmetic_over_byteptr() {
|
||||||
assert q == byteptr(9)
|
assert q == byteptr(9)
|
||||||
s := unsafe { q - 1 }
|
s := unsafe { q - 1 }
|
||||||
assert s == byteptr(8)
|
assert s == byteptr(8)
|
||||||
|
unsafe {
|
||||||
unsafe {q++ q++ q--}
|
q++
|
||||||
|
q++
|
||||||
|
q--
|
||||||
|
}
|
||||||
assert q == byteptr(10)
|
assert q == byteptr(10)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Abc {
|
||||||
|
mut:
|
||||||
|
x int
|
||||||
|
y int
|
||||||
|
z int
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_ptr_arithmetic_over_struct() {
|
||||||
|
mut a := [3]Abc{}
|
||||||
|
a[0].x = 10
|
||||||
|
a[1].x = 100
|
||||||
|
a[2].x = 1000
|
||||||
|
mut pa := &a[0]
|
||||||
|
assert pa == &a[0]
|
||||||
|
unsafe {
|
||||||
|
assert pa.x == 10
|
||||||
|
pa++
|
||||||
|
assert u64(pa) - u64(&a[0]) == sizeof(Abc)
|
||||||
|
assert pa.x == 100
|
||||||
|
pa++
|
||||||
|
assert u64(pa) - u64(&a[0]) == 2 * sizeof(Abc)
|
||||||
|
assert pa.x == 1000
|
||||||
|
pa--
|
||||||
|
assert pa.x == 100
|
||||||
|
pa--
|
||||||
|
assert pa.x == 10
|
||||||
|
pa += 2
|
||||||
|
assert pa.x == 1000
|
||||||
|
pa -= 2
|
||||||
|
}
|
||||||
|
assert pa == &a[0]
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue