checker: allow `*x = y` only inside unsafe blocks
parent
2618b4fbd3
commit
e9177faf17
|
@ -18,6 +18,8 @@ pub fn next(max int) int {
|
||||||
// writes a result value to the seed argument.
|
// writes a result value to the seed argument.
|
||||||
pub fn rand_r(seed &int) int {
|
pub fn rand_r(seed &int) int {
|
||||||
ns := *seed * 1103515245 + 12345
|
ns := *seed * 1103515245 + 12345
|
||||||
|
unsafe {
|
||||||
(*seed) = ns
|
(*seed) = ns
|
||||||
|
}
|
||||||
return ns & 0x7fffffff
|
return ns & 0x7fffffff
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ pub mut:
|
||||||
scope_returns bool
|
scope_returns bool
|
||||||
mod string // current module name
|
mod string // current module name
|
||||||
is_builtin_mod bool // are we in `builtin`?
|
is_builtin_mod bool // are we in `builtin`?
|
||||||
|
inside_unsafe bool
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
|
||||||
|
@ -571,6 +572,14 @@ fn (mut c Checker) assign_expr(mut assign_expr ast.AssignExpr) {
|
||||||
}
|
}
|
||||||
// Make sure the variable is mutable
|
// Make sure the variable is mutable
|
||||||
c.fail_if_immutable(assign_expr.left)
|
c.fail_if_immutable(assign_expr.left)
|
||||||
|
// Do now allow `*x = y` outside `unsafe`
|
||||||
|
if assign_expr.left is ast.PrefixExpr {
|
||||||
|
p := assign_expr.left as ast.PrefixExpr
|
||||||
|
if p.op == .mul && !c.inside_unsafe {
|
||||||
|
c.error('modifying variables via deferencing can only be done in `unsafe` blocks',
|
||||||
|
assign_expr.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
// Single side check
|
// Single side check
|
||||||
match assign_expr.op {
|
match assign_expr.op {
|
||||||
.assign {} // No need to do single side check for =. But here put it first for speed.
|
.assign {} // No need to do single side check for =. But here put it first for speed.
|
||||||
|
@ -1550,7 +1559,9 @@ fn (mut c Checker) stmt(node ast.Stmt) {
|
||||||
c.type_decl(it)
|
c.type_decl(it)
|
||||||
}
|
}
|
||||||
ast.UnsafeStmt {
|
ast.UnsafeStmt {
|
||||||
|
c.inside_unsafe = true
|
||||||
c.stmts(it.stmts)
|
c.stmts(it.stmts)
|
||||||
|
c.inside_unsafe = false
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// println('checker.stmt(): unhandled node')
|
// println('checker.stmt(): unhandled node')
|
||||||
|
|
|
@ -44,6 +44,7 @@ mut:
|
||||||
returns bool
|
returns bool
|
||||||
inside_match bool // to separate `match A { }` from `Struct{}`
|
inside_match bool // to separate `match A { }` from `Struct{}`
|
||||||
inside_match_case bool // to separate `match_expr { }` from `Struct{}`
|
inside_match_case bool // to separate `match_expr { }` from `Struct{}`
|
||||||
|
inside_unsafe bool
|
||||||
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
|
is_stmt_ident bool // true while the beginning of a statement is an ident/selector
|
||||||
expecting_type bool // `is Type`, expecting type
|
expecting_type bool // `is Type`, expecting type
|
||||||
errors []errors.Error
|
errors []errors.Error
|
||||||
|
@ -84,8 +85,8 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
|
||||||
start_pos: 0
|
start_pos: 0
|
||||||
parent: 0
|
parent: 0
|
||||||
}
|
}
|
||||||
errors: []errors.Error{},
|
errors: []errors.Error{}
|
||||||
warnings: []errors.Warning{},
|
warnings: []errors.Warning{}
|
||||||
global_scope: global_scope
|
global_scope: global_scope
|
||||||
}
|
}
|
||||||
// comments_mode: comments_mode
|
// comments_mode: comments_mode
|
||||||
|
@ -128,8 +129,8 @@ pub fn parse_file(path string, b_table &table.Table, comments_mode scanner.Comme
|
||||||
imports: p.ast_imports
|
imports: p.ast_imports
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
scope: p.scope
|
scope: p.scope
|
||||||
global_scope: p.global_scope,
|
global_scope: p.global_scope
|
||||||
errors: p.errors,
|
errors: p.errors
|
||||||
warnings: p.warnings
|
warnings: p.warnings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,7 +327,8 @@ pub fn (mut p Parser) top_stmt() ast.Stmt {
|
||||||
return p.interface_decl()
|
return p.interface_decl()
|
||||||
}
|
}
|
||||||
.key_import {
|
.key_import {
|
||||||
p.error_with_pos('`import x` can only be declared at the beginning of the file', p.tok.position())
|
p.error_with_pos('`import x` can only be declared at the beginning of the file',
|
||||||
|
p.tok.position())
|
||||||
return p.import_stmt()
|
return p.import_stmt()
|
||||||
}
|
}
|
||||||
.key_global {
|
.key_global {
|
||||||
|
@ -433,7 +435,9 @@ pub fn (mut p Parser) stmt() ast.Stmt {
|
||||||
}
|
}
|
||||||
.key_unsafe {
|
.key_unsafe {
|
||||||
p.next()
|
p.next()
|
||||||
|
p.inside_unsafe = true
|
||||||
stmts := p.parse_block()
|
stmts := p.parse_block()
|
||||||
|
p.inside_unsafe = false
|
||||||
return ast.UnsafeStmt{
|
return ast.UnsafeStmt{
|
||||||
stmts: stmts
|
stmts: stmts
|
||||||
}
|
}
|
||||||
|
@ -580,9 +584,9 @@ pub fn (mut p Parser) error_with_pos(s string, pos token.Position) {
|
||||||
exit(1)
|
exit(1)
|
||||||
} else {
|
} else {
|
||||||
p.errors << errors.Error{
|
p.errors << errors.Error{
|
||||||
file_path: p.file_name,
|
file_path: p.file_name
|
||||||
pos: pos,
|
pos: pos
|
||||||
reporter: .parser,
|
reporter: .parser
|
||||||
message: s
|
message: s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,9 +598,9 @@ pub fn (mut p Parser) warn_with_pos(s string, pos token.Position) {
|
||||||
eprintln(ferror)
|
eprintln(ferror)
|
||||||
} else {
|
} else {
|
||||||
p.warnings << errors.Warning{
|
p.warnings << errors.Warning{
|
||||||
file_path: p.file_name,
|
file_path: p.file_name
|
||||||
pos: pos,
|
pos: pos
|
||||||
reporter: .parser,
|
reporter: .parser
|
||||||
message: s
|
message: s
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -212,6 +212,9 @@ fn (mut p Parser) prefix_expr() ast.PrefixExpr {
|
||||||
if op == .amp {
|
if op == .amp {
|
||||||
p.is_amp = true
|
p.is_amp = true
|
||||||
}
|
}
|
||||||
|
// if op == .mul && !p.inside_unsafe {
|
||||||
|
// p.warn('unsafe')
|
||||||
|
// }
|
||||||
p.next()
|
p.next()
|
||||||
right := p.expr(token.Precedence.prefix)
|
right := p.expr(token.Precedence.prefix)
|
||||||
p.is_amp = false
|
p.is_amp = false
|
||||||
|
|
Loading…
Reference in New Issue