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

checker: stricter []&Type{len:x} check

This commit is contained in:
Alexander Medvednikov 2022-07-05 23:51:29 +03:00
parent 9b4dec7b98
commit 163c7ba2bb
10 changed files with 119 additions and 83 deletions

View File

@ -949,23 +949,26 @@ pub fn open_append(path string) ?File {
// Note: this function will NOT return when successfull, since // Note: this function will NOT return when successfull, since
// the child process will take control over execution. // the child process will take control over execution.
pub fn execvp(cmdpath string, cmdargs []string) ? { pub fn execvp(cmdpath string, cmdargs []string) ? {
mut cargs := []&char{} unsafe {
cargs << &char(cmdpath.str) mut cargs := []&char{}
for i in 0 .. cmdargs.len { cargs << &char(cmdpath.str)
cargs << &char(cmdargs[i].str) for i in 0 .. cmdargs.len {
cargs << &char(cmdargs[i].str)
}
cargs << &char(0)
mut res := int(0)
$if windows {
res = C._execvp(&char(cmdpath.str), cargs.data)
} $else {
res = C.execvp(&char(cmdpath.str), cargs.data)
}
if res == -1 {
return error_with_code(posix_get_error_msg(C.errno), C.errno)
}
// just in case C._execvp returned ... that happens on windows ...
exit(res)
} }
cargs << &char(0)
mut res := int(0)
$if windows {
res = C._execvp(&char(cmdpath.str), cargs.data)
} $else {
res = C.execvp(&char(cmdpath.str), cargs.data)
}
if res == -1 {
return error_with_code(posix_get_error_msg(C.errno), C.errno)
}
// just in case C._execvp returned ... that happens on windows ...
exit(res)
} }
// execve - loads and executes a new child process, *in place* of the current process. // execve - loads and executes a new child process, *in place* of the current process.
@ -975,27 +978,29 @@ pub fn execvp(cmdpath string, cmdargs []string) ? {
// Note: this function will NOT return when successfull, since // Note: this function will NOT return when successfull, since
// the child process will take control over execution. // the child process will take control over execution.
pub fn execve(cmdpath string, cmdargs []string, envs []string) ? { pub fn execve(cmdpath string, cmdargs []string, envs []string) ? {
mut cargv := []&char{} unsafe {
mut cenvs := []&char{} mut cargv := []&char{}
cargv << &char(cmdpath.str) mut cenvs := []&char{}
for i in 0 .. cmdargs.len { cargv << &char(cmdpath.str)
cargv << &char(cmdargs[i].str) for i in 0 .. cmdargs.len {
} cargv << &char(cmdargs[i].str)
for i in 0 .. envs.len { }
cenvs << &char(envs[i].str) for i in 0 .. envs.len {
} cenvs << &char(envs[i].str)
cargv << &char(0) }
cenvs << &char(0) cargv << &char(0)
mut res := int(0) cenvs << &char(0)
$if windows { mut res := int(0)
res = C._execve(&char(cmdpath.str), cargv.data, cenvs.data) $if windows {
} $else { res = C._execve(&char(cmdpath.str), cargv.data, cenvs.data)
res = C.execve(&char(cmdpath.str), cargv.data, cenvs.data) } $else {
} res = C.execve(&char(cmdpath.str), cargv.data, cenvs.data)
// Note: normally execve does not return at all. }
// If it returns, then something went wrong... // Note: normally execve does not return at all.
if res == -1 { // If it returns, then something went wrong...
return error_with_code(posix_get_error_msg(C.errno), C.errno) if res == -1 {
return error_with_code(posix_get_error_msg(C.errno), C.errno)
}
} }
} }

View File

@ -81,17 +81,19 @@ pub fn (mut pool PoolProcessor) work_on_pointers(items []voidptr) {
if pool.njobs > 0 { if pool.njobs > 0 {
njobs = pool.njobs njobs = pool.njobs
} }
pool.thread_contexts = []voidptr{len: items.len} unsafe {
pool.results = []voidptr{len: items.len} pool.thread_contexts = []voidptr{len: items.len}
pool.items = []voidptr{cap: items.len} pool.results = []voidptr{len: items.len}
pool.items << items pool.items = []voidptr{cap: items.len}
pool.waitgroup.add(njobs) pool.items << items
for i := 0; i < njobs; i++ { pool.waitgroup.add(njobs)
if njobs > 1 { for i := 0; i < njobs; i++ {
go process_in_thread(mut pool, i) if njobs > 1 {
} else { go process_in_thread(mut pool, i)
// do not run concurrently, just use the same thread: } else {
process_in_thread(mut pool, i) // do not run concurrently, just use the same thread:
process_in_thread(mut pool, i)
}
} }
} }
pool.waitgroup.wait() pool.waitgroup.wait()
@ -136,11 +138,13 @@ pub fn (pool &PoolProcessor) get_results<T>() []T {
// get_results_ref - get a list of type safe results in the main thread. // get_results_ref - get a list of type safe results in the main thread.
pub fn (pool &PoolProcessor) get_results_ref<T>() []&T { pub fn (pool &PoolProcessor) get_results_ref<T>() []&T {
mut res := []&T{cap: pool.results.len} unsafe {
for i in 0 .. pool.results.len { mut res := []&T{cap: pool.results.len}
res << &T(pool.results[i]) for i in 0 .. pool.results.len {
res << &T(pool.results[i])
}
return res
} }
return res
} }
// set_shared_context - can be called during the setup so that you can // set_shared_context - can be called during the setup so that you can

View File

@ -251,17 +251,19 @@ pub fn (mut b Builder) resolve_deps() {
eprintln(mods.str()) eprintln(mods.str())
eprintln('-------------------------------') eprintln('-------------------------------')
} }
mut reordered_parsed_files := []&ast.File{} unsafe {
for m in mods { mut reordered_parsed_files := []&ast.File{}
for pf in b.parsed_files { for m in mods {
if m == pf.mod.name { for pf in b.parsed_files {
reordered_parsed_files << pf if m == pf.mod.name {
// eprintln('pf.mod.name: $pf.mod.name | pf.path: $pf.path') reordered_parsed_files << pf
// eprintln('pf.mod.name: $pf.mod.name | pf.path: $pf.path')
}
} }
} }
b.table.modules = mods
b.parsed_files = reordered_parsed_files
} }
b.table.modules = mods
b.parsed_files = reordered_parsed_files
} }
// graph of all imported modules // graph of all imported modules

View File

@ -271,9 +271,10 @@ pub fn (mut c Checker) check_files(ast_files []&ast.File) {
// c.files = ast_files // c.files = ast_files
mut has_main_mod_file := false mut has_main_mod_file := false
mut has_main_fn := false mut has_main_fn := false
unsafe {
mut files_from_main_module := []&ast.File{} mut files_from_main_module := []&ast.File{}
for i in 0 .. ast_files.len { for i in 0 .. ast_files.len {
mut file := unsafe { ast_files[i] } mut file := ast_files[i]
c.timers.start('checker_check $file.path') c.timers.start('checker_check $file.path')
c.check(file) c.check(file)
if file.mod.name == 'main' { if file.mod.name == 'main' {
@ -302,6 +303,7 @@ pub fn (mut c Checker) check_files(ast_files []&ast.File) {
has_main_fn = true has_main_fn = true
} }
} }
}
c.timers.start('checker_post_process_generic_fns') c.timers.start('checker_post_process_generic_fns')
last_file := c.file last_file := c.file
// post process generic functions. must be done after all files have been // post process generic functions. must be done after all files have been

View File

@ -56,6 +56,13 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type {
&& c.table.cur_fn.generic_names.len == 0 { && c.table.cur_fn.generic_names.len == 0 {
c.error('generic struct cannot use in non-generic function', node.pos) c.error('generic struct cannot use in non-generic function', node.pos)
} }
// &int{} check
if node.elem_type.is_any_kind_of_pointer() && !c.inside_unsafe
&& (node.has_len || node.has_cap) {
c.warn('arrays of references need to be initialized right away (unless used inside `unsafe`)',
node.pos)
}
return node.typ return node.typ
} }
if node.is_fixed { if node.is_fixed {

View File

@ -0,0 +1,7 @@
vlib/v/checker/tests/sum.vv:2:14: warning: arrays of references need to be initialized right away (unless used inside `unsafe`)
1 | fn main() {
2 | println(*[]&int{len: 1}[0])
| ~~~~~~~
3 | }
4 |

View File

@ -0,0 +1,3 @@
fn main() {
println(*[]&int{len: 1}[0])
}

View File

@ -4896,14 +4896,16 @@ fn (mut g Gen) write_sorted_types() {
defer { defer {
g.type_definitions.writeln('// #end sorted_symbols') g.type_definitions.writeln('// #end sorted_symbols')
} }
mut symbols := []&ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted unsafe {
for sym in g.table.type_symbols { mut symbols := []&ast.TypeSymbol{cap: g.table.type_symbols.len} // structs that need to be sorted
if sym.name !in c.builtins { for sym in g.table.type_symbols {
symbols << sym if sym.name !in c.builtins {
symbols << sym
}
} }
sorted_symbols := g.sort_structs(symbols)
g.write_types(sorted_symbols)
} }
sorted_symbols := g.sort_structs(symbols)
g.write_types(sorted_symbols)
} }
fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) { fn (mut g Gen) write_types(symbols []&ast.TypeSymbol) {
@ -5186,11 +5188,13 @@ fn (mut g Gen) sort_structs(typesa []&ast.TypeSymbol) []&ast.TypeSymbol {
'\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro') '\nif you feel this is an error, please create a new issue here: https://github.com/vlang/v/issues and tag @joe-conigliaro')
} }
// sort types // sort types
mut sorted_symbols := []&ast.TypeSymbol{cap: dep_graph_sorted.nodes.len} unsafe {
for node in dep_graph_sorted.nodes { mut sorted_symbols := []&ast.TypeSymbol{cap: dep_graph_sorted.nodes.len}
sorted_symbols << g.table.sym_by_idx(g.table.type_idxs[node.name]) for node in dep_graph_sorted.nodes {
sorted_symbols << g.table.sym_by_idx(g.table.type_idxs[node.name])
}
return sorted_symbols
} }
return sorted_symbols
} }
[inline] [inline]

View File

@ -99,7 +99,7 @@ pub mut:
vet_errors []vet.Error vet_errors []vet.Error
} }
__global codegen_files = []&ast.File{} __global codegen_files = unsafe { []&ast.File{} }
// for tests // for tests
pub fn parse_stmt(text string, table &ast.Table, scope &ast.Scope) ast.Stmt { pub fn parse_stmt(text string, table &ast.Table, scope &ast.Scope) ast.Stmt {
@ -425,17 +425,19 @@ pub fn parse_files(paths []string, table &ast.Table, pref &pref.Preferences) []&
} }
*/ */
} }
mut files := []&ast.File{cap: paths.len} unsafe {
for path in paths { mut files := []&ast.File{cap: paths.len}
timers.start('parse_file $path') for path in paths {
files << parse_file(path, table, .skip_comments, pref) timers.start('parse_file $path')
timers.show('parse_file $path') files << parse_file(path, table, .skip_comments, pref)
timers.show('parse_file $path')
}
if codegen_files.len > 0 {
files << codegen_files
codegen_files.clear()
}
return files
} }
if codegen_files.len > 0 {
files << codegen_files
codegen_files.clear()
}
return files
} }
// codegen allows you to generate V code, so that it can be parsed, // codegen allows you to generate V code, so that it can be parsed,

View File

@ -39,7 +39,7 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl {
if p.disallow_declarations_in_script_mode() { if p.disallow_declarations_in_script_mode() {
return ast.StructDecl{} return ast.StructDecl{}
} }
mut name := if is_anon { '' } else { p.check_name()} mut name := if is_anon { '' } else { p.check_name() }
if name.len == 1 && name[0].is_capital() { if name.len == 1 && name[0].is_capital() {
p.error_with_pos('single letter capital names are reserved for generic template types.', p.error_with_pos('single letter capital names are reserved for generic template types.',
name_pos) name_pos)