mirror of
https://github.com/vlang/v.git
synced 2025-09-13 14:32:26 +03:00
checker: disallow struct int to ptr outside unsafe (#17923)
This commit is contained in:
parent
92cb7468ce
commit
3d99f1f2c2
36 changed files with 124 additions and 47 deletions
|
@ -704,7 +704,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
fn init_settings() {
|
fn init_settings() {
|
||||||
mut s := &VpmSettings(0)
|
mut s := &VpmSettings(unsafe { nil })
|
||||||
unsafe {
|
unsafe {
|
||||||
s = settings
|
s = settings
|
||||||
}
|
}
|
||||||
|
|
|
@ -6188,12 +6188,12 @@ fn my_callback(arg voidptr, howmany int, cvalues &&char, cnames &&char) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
db := &C.sqlite3(0) // this means `sqlite3* db = 0`
|
db := &C.sqlite3(unsafe { nil }) // this means `sqlite3* db = 0`
|
||||||
// passing a string literal to a C function call results in a C string, not a V string
|
// passing a string literal to a C function call results in a C string, not a V string
|
||||||
C.sqlite3_open(c'users.db', &db)
|
C.sqlite3_open(c'users.db', &db)
|
||||||
// C.sqlite3_open(db_path.str, &db)
|
// C.sqlite3_open(db_path.str, &db)
|
||||||
query := 'select count(*) from users'
|
query := 'select count(*) from users'
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
// Note: You can also use the `.str` field of a V string,
|
// Note: You can also use the `.str` field of a V string,
|
||||||
// to get its C style zero terminated representation
|
// to get its C style zero terminated representation
|
||||||
C.sqlite3_prepare_v2(db, &char(query.str), -1, &stmt, 0)
|
C.sqlite3_prepare_v2(db, &char(query.str), -1, &stmt, 0)
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub fn (mut s System) init(sc SystemConfig) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut s System) update(dt f64) {
|
pub fn (mut s System) update(dt f64) {
|
||||||
mut p := &Particle(0)
|
mut p := &Particle(unsafe { nil })
|
||||||
mut moved := 0
|
mut moved := 0
|
||||||
for i := 0; i < s.pool.len; i++ {
|
for i := 0; i < s.pool.len; i++ {
|
||||||
p = s.pool[i]
|
p = s.pool[i]
|
||||||
|
@ -70,7 +70,7 @@ pub fn (mut s System) reset() {
|
||||||
pub fn (mut s System) explode(x f32, y f32) {
|
pub fn (mut s System) explode(x f32, y f32) {
|
||||||
mut reserve := 500
|
mut reserve := 500
|
||||||
center := vec.Vec2[f64]{x, y}
|
center := vec.Vec2[f64]{x, y}
|
||||||
mut p := &Particle(0)
|
mut p := &Particle(unsafe { nil })
|
||||||
mut moved := 0
|
mut moved := 0
|
||||||
for i := 0; i < s.bin.len && reserve > 0; i++ {
|
for i := 0; i < s.bin.len && reserve > 0; i++ {
|
||||||
p = s.bin[i]
|
p = s.bin[i]
|
||||||
|
|
|
@ -70,7 +70,7 @@ fn new_node() &mapnode {
|
||||||
fn (mut m SortedMap) set(key string, value voidptr) {
|
fn (mut m SortedMap) set(key string, value voidptr) {
|
||||||
mut node := m.root
|
mut node := m.root
|
||||||
mut child_index := 0
|
mut child_index := 0
|
||||||
mut parent := &mapnode(0)
|
mut parent := &mapnode(unsafe { nil })
|
||||||
for {
|
for {
|
||||||
if node.len == max_len {
|
if node.len == max_len {
|
||||||
if parent == unsafe { nil } {
|
if parent == unsafe { nil } {
|
||||||
|
@ -228,7 +228,7 @@ fn (mut n mapnode) remove_key(k string) bool {
|
||||||
n.fill(idx)
|
n.fill(idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
mut node := &mapnode(0)
|
mut node := &mapnode(unsafe { nil })
|
||||||
if flag && idx > n.len {
|
if flag && idx > n.len {
|
||||||
node = unsafe { &mapnode(n.children[idx - 1]) }
|
node = unsafe { &mapnode(n.children[idx - 1]) }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -63,7 +63,7 @@ fn C.mysql_stmt_next_result(&C.MYSQL_STMT) int
|
||||||
fn C.mysql_stmt_store_result(&C.MYSQL_STMT) int
|
fn C.mysql_stmt_store_result(&C.MYSQL_STMT) int
|
||||||
|
|
||||||
pub struct Stmt {
|
pub struct Stmt {
|
||||||
stmt &C.MYSQL_STMT = &C.MYSQL_STMT(0)
|
stmt &C.MYSQL_STMT = &C.MYSQL_STMT(unsafe { nil })
|
||||||
query string
|
query string
|
||||||
mut:
|
mut:
|
||||||
binds []C.MYSQL_BIND
|
binds []C.MYSQL_BIND
|
||||||
|
|
|
@ -127,7 +127,7 @@ fn C.sqlite3_changes(&C.sqlite3) int
|
||||||
|
|
||||||
// connect Opens the connection with a database.
|
// connect Opens the connection with a database.
|
||||||
pub fn connect(path string) !DB {
|
pub fn connect(path string) !DB {
|
||||||
db := &C.sqlite3(0)
|
db := &C.sqlite3(unsafe { nil })
|
||||||
code := C.sqlite3_open(&char(path.str), &db)
|
code := C.sqlite3_open(&char(path.str), &db)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return &SQLError{
|
return &SQLError{
|
||||||
|
@ -182,7 +182,7 @@ pub fn (db &DB) get_affected_rows_count() int {
|
||||||
|
|
||||||
// q_int returns a single integer value, from the first column of the result of executing `query`
|
// q_int returns a single integer value, from the first column of the result of executing `query`
|
||||||
pub fn (db &DB) q_int(query string) int {
|
pub fn (db &DB) q_int(query string) int {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ pub fn (db &DB) q_int(query string) int {
|
||||||
|
|
||||||
// q_string returns a single string value, from the first column of the result of executing `query`
|
// q_string returns a single string value, from the first column of the result of executing `query`
|
||||||
pub fn (db &DB) q_string(query string) string {
|
pub fn (db &DB) q_string(query string) string {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -210,7 +210,7 @@ pub fn (db &DB) q_string(query string) string {
|
||||||
// Result codes: https://www.sqlite.org/rescode.html
|
// Result codes: https://www.sqlite.org/rescode.html
|
||||||
[manualfree]
|
[manualfree]
|
||||||
pub fn (db &DB) exec(query string) ([]Row, int) {
|
pub fn (db &DB) exec(query string) ([]Row, int) {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -278,7 +278,7 @@ pub fn (db &DB) error_message(code int, query string) IError {
|
||||||
// Use it, in case you don't expect any row results, but still want a result code.
|
// Use it, in case you don't expect any row results, but still want a result code.
|
||||||
// e.g. for queries like these: `INSERT INTO ... VALUES (...)`
|
// e.g. for queries like these: `INSERT INTO ... VALUES (...)`
|
||||||
pub fn (db &DB) exec_none(query string) int {
|
pub fn (db &DB) exec_none(query string) int {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
||||||
code := C.sqlite3_step(stmt)
|
code := C.sqlite3_step(stmt)
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
|
|
|
@ -8,7 +8,7 @@ fn C.sqlite3_bind_text(&C.sqlite3_stmt, int, &char, int, voidptr) int
|
||||||
// Only for V ORM
|
// Only for V ORM
|
||||||
fn (db &DB) init_stmt(query string) (&C.sqlite3_stmt, int) {
|
fn (db &DB) init_stmt(query string) (&C.sqlite3_stmt, int) {
|
||||||
// println('init_stmt("$query")')
|
// println('init_stmt("$query")')
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
err := C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
err := C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
||||||
return stmt, err
|
return stmt, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub enum OpenModeFlag {
|
||||||
// connect_full Opens connection to sqlite database. It gives more control than `open`.
|
// connect_full Opens connection to sqlite database. It gives more control than `open`.
|
||||||
// Flags give control over readonly and create decisions. Specific VFS can be chosen.
|
// Flags give control over readonly and create decisions. Specific VFS can be chosen.
|
||||||
pub fn connect_full(path string, mode_flags []OpenModeFlag, vfs_name string) !DB {
|
pub fn connect_full(path string, mode_flags []OpenModeFlag, vfs_name string) !DB {
|
||||||
db := &C.sqlite3(0)
|
db := &C.sqlite3(unsafe { nil })
|
||||||
|
|
||||||
mut flags := 0
|
mut flags := 0
|
||||||
|
|
||||||
|
|
|
@ -1355,7 +1355,7 @@ fn (mut dl Dlmalloc) segment_holding(ptr voidptr) &Segment {
|
||||||
}
|
}
|
||||||
sp = sp.next
|
sp = sp.next
|
||||||
}
|
}
|
||||||
return &Segment(0)
|
return &Segment(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
// realloc behaves as libc realloc, but operates within the given space
|
// realloc behaves as libc realloc, but operates within the given space
|
||||||
|
|
|
@ -194,7 +194,7 @@ pub fn resolve_ipaddrs(addr string, family AddrFamily, typ SocketType) ![]Addr {
|
||||||
hints.ai_socktype = int(typ)
|
hints.ai_socktype = int(typ)
|
||||||
hints.ai_flags = C.AI_PASSIVE
|
hints.ai_flags = C.AI_PASSIVE
|
||||||
|
|
||||||
results := &C.addrinfo(0)
|
results := &C.addrinfo(unsafe { nil })
|
||||||
|
|
||||||
sport := '${port}'
|
sport := '${port}'
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
// infinite timeout is signaled by passing null as the timeout to
|
||||||
// select
|
// select
|
||||||
if timeout == net.infinite_timeout {
|
if timeout == net.infinite_timeout {
|
||||||
timeval_timeout = &C.timeval(0)
|
timeval_timeout = &C.timeval(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
match test {
|
match test {
|
||||||
|
|
|
@ -379,7 +379,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
// infinite timeout is signaled by passing null as the timeout to
|
||||||
// select
|
// select
|
||||||
if timeout == net.infinite_timeout {
|
if timeout == net.infinite_timeout {
|
||||||
timeval_timeout = &C.timeval(0)
|
timeval_timeout = &C.timeval(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
match test {
|
match test {
|
||||||
|
|
|
@ -5,7 +5,7 @@ struct Abc {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_printing_struct_with_reference_field_of_type_ssl_ctx() {
|
fn test_printing_struct_with_reference_field_of_type_ssl_ctx() {
|
||||||
a := Abc{&C.SSL_CTX(123)}
|
a := unsafe { Abc{&C.SSL_CTX(123)} }
|
||||||
dump(a)
|
dump(a)
|
||||||
sa := a.str()
|
sa := a.str()
|
||||||
assert sa.contains('&C.SSL_CTX(0x7b)')
|
assert sa.contains('&C.SSL_CTX(0x7b)')
|
||||||
|
|
|
@ -436,7 +436,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
// infinite timeout is signaled by passing null as the timeout to
|
||||||
// select
|
// select
|
||||||
if timeout == net.infinite_timeout {
|
if timeout == net.infinite_timeout {
|
||||||
timeval_timeout = &C.timeval(0)
|
timeval_timeout = &C.timeval(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
match test {
|
match test {
|
||||||
|
|
|
@ -42,7 +42,7 @@ fn @select(handle int, test Select, timeout time.Duration) !bool {
|
||||||
// infinite timeout is signaled by passing null as the timeout to
|
// infinite timeout is signaled by passing null as the timeout to
|
||||||
// select
|
// select
|
||||||
if timeout == unix.infinite_timeout {
|
if timeout == unix.infinite_timeout {
|
||||||
timeval_timeout = &C.timeval(0)
|
timeval_timeout = &C.timeval(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
match test {
|
match test {
|
||||||
|
|
|
@ -272,7 +272,7 @@ pub fn ls(path string) ![]string {
|
||||||
if isnil(dir) {
|
if isnil(dir) {
|
||||||
return error('ls() couldnt open dir "${path}"')
|
return error('ls() couldnt open dir "${path}"')
|
||||||
}
|
}
|
||||||
mut ent := &C.dirent(0)
|
mut ent := &C.dirent(unsafe { nil })
|
||||||
// mut ent := &C.dirent{!}
|
// mut ent := &C.dirent{!}
|
||||||
for {
|
for {
|
||||||
ent = C.readdir(dir)
|
ent = C.readdir(dir)
|
||||||
|
|
|
@ -126,7 +126,7 @@ fn C.sqlite3_changes(&C.sqlite3) int
|
||||||
|
|
||||||
// connect Opens the connection with a database.
|
// connect Opens the connection with a database.
|
||||||
pub fn connect(path string) !DB {
|
pub fn connect(path string) !DB {
|
||||||
db := &C.sqlite3(0)
|
db := &C.sqlite3(unsafe { nil })
|
||||||
code := C.sqlite3_open(&char(path.str), &db)
|
code := C.sqlite3_open(&char(path.str), &db)
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
return &SQLError{
|
return &SQLError{
|
||||||
|
@ -181,7 +181,7 @@ pub fn (db &DB) get_affected_rows_count() int {
|
||||||
|
|
||||||
// Returns a single cell with value int.
|
// Returns a single cell with value int.
|
||||||
pub fn (db &DB) q_int(query string) int {
|
pub fn (db &DB) q_int(query string) int {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ pub fn (db &DB) q_int(query string) int {
|
||||||
|
|
||||||
// Returns a single cell with value string.
|
// Returns a single cell with value string.
|
||||||
pub fn (db &DB) q_string(query string) string {
|
pub fn (db &DB) q_string(query string) string {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -209,7 +209,7 @@ pub fn (db &DB) q_string(query string) string {
|
||||||
// Result codes: https://www.sqlite.org/rescode.html
|
// Result codes: https://www.sqlite.org/rescode.html
|
||||||
[manualfree]
|
[manualfree]
|
||||||
pub fn (db &DB) exec(query string) ([]Row, int) {
|
pub fn (db &DB) exec(query string) ([]Row, int) {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
defer {
|
defer {
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ pub fn (db &DB) error_message(code int, query string) IError {
|
||||||
// In case you don't expect any row results, but still want a result code.
|
// In case you don't expect any row results, but still want a result code.
|
||||||
// e.g. INSERT INTO ... VALUES (...)
|
// e.g. INSERT INTO ... VALUES (...)
|
||||||
pub fn (db &DB) exec_none(query string) int {
|
pub fn (db &DB) exec_none(query string) int {
|
||||||
stmt := &C.sqlite3_stmt(0)
|
stmt := &C.sqlite3_stmt(unsafe { nil })
|
||||||
C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
C.sqlite3_prepare_v2(db.conn, &char(query.str), query.len, &stmt, 0)
|
||||||
code := C.sqlite3_step(stmt)
|
code := C.sqlite3_step(stmt)
|
||||||
C.sqlite3_finalize(stmt)
|
C.sqlite3_finalize(stmt)
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub enum OpenModeFlag {
|
||||||
// connect_full Opens connection to sqlite database. It gives more control than `open`.
|
// connect_full Opens connection to sqlite database. It gives more control than `open`.
|
||||||
// Flags give control over readonly and create decisions. Specific VFS can be chosen.
|
// Flags give control over readonly and create decisions. Specific VFS can be chosen.
|
||||||
pub fn connect_full(path string, mode_flags []OpenModeFlag, vfs_name string) !DB {
|
pub fn connect_full(path string, mode_flags []OpenModeFlag, vfs_name string) !DB {
|
||||||
db := &C.sqlite3(0)
|
db := &C.sqlite3(unsafe { nil })
|
||||||
|
|
||||||
mut flags := 0
|
mut flags := 0
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ mut:
|
||||||
read_all_bytes bool = true
|
read_all_bytes bool = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const ctx_ptr = &Context(0)
|
const ctx_ptr = &Context(unsafe { nil })
|
||||||
|
|
||||||
// init initializes the terminal console with Config `cfg`.
|
// init initializes the terminal console with Config `cfg`.
|
||||||
pub fn init(cfg Config) &Context {
|
pub fn init(cfg Config) &Context {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import time
|
||||||
|
|
||||||
const buf_size = 64
|
const buf_size = 64
|
||||||
|
|
||||||
const ctx_ptr = &Context(0)
|
const ctx_ptr = &Context(unsafe { nil })
|
||||||
|
|
||||||
const stdin_at_startup = u32(0)
|
const stdin_at_startup = u32(0)
|
||||||
|
|
||||||
|
|
|
@ -255,7 +255,7 @@ fn (mut ctx Context) parse_events() {
|
||||||
if nr_iters > 100 {
|
if nr_iters > 100 {
|
||||||
ctx.shift(1)
|
ctx.shift(1)
|
||||||
}
|
}
|
||||||
mut event := &Event(0)
|
mut event := &Event(unsafe { nil })
|
||||||
if ctx.read_buf[0] == 0x1b {
|
if ctx.read_buf[0] == 0x1b {
|
||||||
e, len := escape_sequence(ctx.read_buf.bytestr())
|
e, len := escape_sequence(ctx.read_buf.bytestr())
|
||||||
event = e
|
event = e
|
||||||
|
@ -420,7 +420,7 @@ fn escape_sequence(buf_ string) (&Event, int) {
|
||||||
if buf.len > 2 && buf[1] == `<` {
|
if buf.len > 2 && buf[1] == `<` {
|
||||||
split := buf[2..].split(';')
|
split := buf[2..].split(';')
|
||||||
if split.len < 3 {
|
if split.len < 3 {
|
||||||
return &Event(0), 0
|
return &Event(unsafe { nil }), 0
|
||||||
}
|
}
|
||||||
|
|
||||||
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
typ, x, y := split[0].int(), split[1].int(), split[2].int()
|
||||||
|
|
|
@ -4,7 +4,7 @@ import toml.to
|
||||||
import toml.ast
|
import toml.ast
|
||||||
|
|
||||||
const empty_toml_document = toml.Doc{
|
const empty_toml_document = toml.Doc{
|
||||||
ast: &ast.Root(0)
|
ast: &ast.Root(unsafe { nil })
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -102,7 +102,7 @@ pub fn new_table() &Table {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
__global global_table = &Table(0)
|
__global global_table = &Table(unsafe { nil })
|
||||||
|
|
||||||
pub fn set_global_table(t &Table) {
|
pub fn set_global_table(t &Table) {
|
||||||
global_table = t
|
global_table = t
|
||||||
|
|
|
@ -2836,6 +2836,30 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
|
||||||
if from_sym.kind == .alias {
|
if from_sym.kind == .alias {
|
||||||
from_type = (from_sym.info as ast.Alias).parent_type.derive_add_muls(from_type)
|
from_type = (from_sym.info as ast.Alias).parent_type.derive_add_muls(from_type)
|
||||||
}
|
}
|
||||||
|
if mut node.expr is ast.IntegerLiteral {
|
||||||
|
if node.expr.val.int() == 0 && !c.pref.translated && !c.file.is_translated {
|
||||||
|
c.error('cannot null cast a struct pointer, use &${to_sym.name}(unsafe { nil })',
|
||||||
|
node.pos)
|
||||||
|
} else if !c.inside_unsafe && !c.pref.translated && !c.file.is_translated {
|
||||||
|
c.error('cannot cast int to a struct pointer outside `unsafe`', node.pos)
|
||||||
|
}
|
||||||
|
} else if mut node.expr is ast.Ident {
|
||||||
|
match mut node.expr.obj {
|
||||||
|
ast.GlobalField, ast.ConstField, ast.Var {
|
||||||
|
if mut node.expr.obj.expr is ast.IntegerLiteral {
|
||||||
|
if node.expr.obj.expr.val.int() == 0 && !c.pref.translated
|
||||||
|
&& !c.file.is_translated {
|
||||||
|
c.error('cannot null cast a struct pointer, use &${to_sym.name}(unsafe { nil })',
|
||||||
|
node.pos)
|
||||||
|
} else if !c.inside_unsafe && !c.pref.translated && !c.file.is_translated {
|
||||||
|
c.error('cannot cast int to a struct pointer outside `unsafe`',
|
||||||
|
node.pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
}
|
||||||
if from_type == ast.voidptr_type_idx && !c.inside_unsafe {
|
if from_type == ast.voidptr_type_idx && !c.inside_unsafe {
|
||||||
// TODO make this an error
|
// TODO make this an error
|
||||||
c.warn('cannot cast voidptr to a struct outside `unsafe`', node.pos)
|
c.warn('cannot cast voidptr to a struct outside `unsafe`', node.pos)
|
||||||
|
@ -3611,9 +3635,10 @@ fn (mut c Checker) lock_expr(mut node ast.LockExpr) ast.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut c Checker) unsafe_expr(mut node ast.UnsafeExpr) ast.Type {
|
fn (mut c Checker) unsafe_expr(mut node ast.UnsafeExpr) ast.Type {
|
||||||
|
prev_unsafe := c.inside_unsafe
|
||||||
c.inside_unsafe = true
|
c.inside_unsafe = true
|
||||||
t := c.expr(node.expr)
|
t := c.expr(node.expr)
|
||||||
c.inside_unsafe = false
|
c.inside_unsafe = prev_unsafe
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:6:5: error: cannot cast int to a struct pointer outside `unsafe`
|
||||||
|
4 | a := 1
|
||||||
|
5 |
|
||||||
|
6 | _ = &Context(a)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
7 | _ = &Context(b)
|
||||||
|
8 | _ = &Context(1)
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:7:5: error: cannot cast int to a struct pointer outside `unsafe`
|
||||||
|
5 |
|
||||||
|
6 | _ = &Context(a)
|
||||||
|
7 | _ = &Context(b)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
8 | _ = &Context(1)
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:8:5: error: cannot cast int to a struct pointer outside `unsafe`
|
||||||
|
6 | _ = &Context(a)
|
||||||
|
7 | _ = &Context(b)
|
||||||
|
8 | _ = &Context(1)
|
||||||
|
| ~~~~~~~~~~~
|
|
@ -0,0 +1,8 @@
|
||||||
|
struct Context {}
|
||||||
|
|
||||||
|
const b = 1
|
||||||
|
a := 1
|
||||||
|
|
||||||
|
_ = &Context(a)
|
||||||
|
_ = &Context(b)
|
||||||
|
_ = &Context(1)
|
18
vlib/v/checker/tests/struct_ptr_cast_zero_err.out
Normal file
18
vlib/v/checker/tests/struct_ptr_cast_zero_err.out
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:6:5: error: cannot null cast a struct pointer, use &Context(unsafe { nil })
|
||||||
|
4 | b := 0
|
||||||
|
5 |
|
||||||
|
6 | _ = &Context(0)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
7 | _ = &Context(a)
|
||||||
|
8 | _ = &Context(b)
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:7:5: error: cannot null cast a struct pointer, use &Context(unsafe { nil })
|
||||||
|
5 |
|
||||||
|
6 | _ = &Context(0)
|
||||||
|
7 | _ = &Context(a)
|
||||||
|
| ~~~~~~~~~~~
|
||||||
|
8 | _ = &Context(b)
|
||||||
|
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:8:5: error: cannot null cast a struct pointer, use &Context(unsafe { nil })
|
||||||
|
6 | _ = &Context(0)
|
||||||
|
7 | _ = &Context(a)
|
||||||
|
8 | _ = &Context(b)
|
||||||
|
| ~~~~~~~~~~~
|
8
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv
Normal file
8
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
struct Context {}
|
||||||
|
|
||||||
|
const a = 0
|
||||||
|
b := 0
|
||||||
|
|
||||||
|
_ = &Context(0)
|
||||||
|
_ = &Context(a)
|
||||||
|
_ = &Context(b)
|
|
@ -428,7 +428,7 @@ pub fn (mut g JsGen) enter_namespace(name string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut g JsGen) escape_namespace() {
|
pub fn (mut g JsGen) escape_namespace() {
|
||||||
g.ns = &Namespace(0)
|
g.ns = &Namespace(unsafe { nil })
|
||||||
g.inside_builtin = false
|
g.inside_builtin = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,7 +179,7 @@ pub fn (mut p Parser) free_scanner() {
|
||||||
unsafe {
|
unsafe {
|
||||||
if p.scanner != 0 {
|
if p.scanner != 0 {
|
||||||
p.scanner.free()
|
p.scanner.free()
|
||||||
p.scanner = &scanner.Scanner(0)
|
p.scanner = &scanner.Scanner(nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ pub fn (mut m Main) run() !string {
|
||||||
}
|
}
|
||||||
// m.opt = options
|
// m.opt = options
|
||||||
opt := m.opt
|
opt := m.opt
|
||||||
mut pc := &PkgConfig(0)
|
mut pc := &PkgConfig(unsafe { nil })
|
||||||
mut res := m.res
|
mut res := m.res
|
||||||
for arg in opt.args {
|
for arg in opt.args {
|
||||||
mut pcdep := load(arg, options) or {
|
mut pcdep := load(arg, options) or {
|
||||||
|
|
|
@ -41,11 +41,11 @@ struct Foo {
|
||||||
type Alias = Foo
|
type Alias = Foo
|
||||||
|
|
||||||
fn test_cast_to_alias_of_ref_struct() {
|
fn test_cast_to_alias_of_ref_struct() {
|
||||||
foo := &Foo(0)
|
foo := &Foo(unsafe { nil })
|
||||||
println(typeof(foo).name)
|
println(typeof(foo).name)
|
||||||
assert typeof(foo).name == '&Foo'
|
assert typeof(foo).name == '&Foo'
|
||||||
|
|
||||||
bar := &Alias(0)
|
bar := &Alias(unsafe { nil })
|
||||||
println(typeof(bar).name)
|
println(typeof(bar).name)
|
||||||
assert typeof(bar).name == '&Alias'
|
assert typeof(bar).name == '&Alias'
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn new_keywords_matcher_trie[T](kw_map map[string]T) KeywordsMatcherTrie {
|
||||||
nodes: []&TrieNode{cap: 20}
|
nodes: []&TrieNode{cap: 20}
|
||||||
}
|
}
|
||||||
for _ in 0 .. 20 {
|
for _ in 0 .. 20 {
|
||||||
km.nodes << &TrieNode(0)
|
km.nodes << &TrieNode(unsafe { nil })
|
||||||
}
|
}
|
||||||
for k, v in kw_map {
|
for k, v in kw_map {
|
||||||
km.add_word(k, int(v))
|
km.add_word(k, int(v))
|
||||||
|
|
|
@ -297,7 +297,7 @@ mut:
|
||||||
|
|
||||||
[unsafe]
|
[unsafe]
|
||||||
pub fn cached_read_source_file(path string) !string {
|
pub fn cached_read_source_file(path string) !string {
|
||||||
mut static cache := &SourceCache(0)
|
mut static cache := &SourceCache(unsafe { nil })
|
||||||
if cache == unsafe { nil } {
|
if cache == unsafe { nil } {
|
||||||
cache = &SourceCache{}
|
cache = &SourceCache{}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ pub fn cached_read_source_file(path string) !string {
|
||||||
if path.len == 0 {
|
if path.len == 0 {
|
||||||
unsafe { cache.sources.free() }
|
unsafe { cache.sources.free() }
|
||||||
unsafe { free(cache) }
|
unsafe { free(cache) }
|
||||||
cache = &SourceCache(0)
|
cache = &SourceCache(unsafe { nil })
|
||||||
return error('memory source file cache cleared')
|
return error('memory source file cache cleared')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,7 +267,7 @@ struct SimpleTcpClientConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_tcp_client(config SimpleTcpClientConfig) !string {
|
fn simple_tcp_client(config SimpleTcpClientConfig) !string {
|
||||||
mut client := &net.TcpConn(0)
|
mut client := &net.TcpConn(unsafe { nil })
|
||||||
mut tries := 0
|
mut tries := 0
|
||||||
for tries < config.retries {
|
for tries < config.retries {
|
||||||
tries++
|
tries++
|
||||||
|
@ -308,7 +308,7 @@ ${config.content}'
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_tcp_client_post_json(config SimpleTcpClientConfig) !string {
|
fn simple_tcp_client_post_json(config SimpleTcpClientConfig) !string {
|
||||||
mut client := &net.TcpConn(0)
|
mut client := &net.TcpConn(unsafe { nil })
|
||||||
mut tries := 0
|
mut tries := 0
|
||||||
for tries < config.retries {
|
for tries < config.retries {
|
||||||
tries++
|
tries++
|
||||||
|
|
|
@ -266,7 +266,7 @@ struct SimpleTcpClientConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simple_tcp_client(config SimpleTcpClientConfig) !string {
|
fn simple_tcp_client(config SimpleTcpClientConfig) !string {
|
||||||
mut client := &net.TcpConn(0)
|
mut client := &net.TcpConn(unsafe { nil })
|
||||||
mut tries := 0
|
mut tries := 0
|
||||||
for tries < config.retries {
|
for tries < config.retries {
|
||||||
tries++
|
tries++
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue