table/checker: verify private functions/methods
							parent
							
								
									af30bf939e
								
							
						
					
					
						commit
						06c1b9e95e
					
				| 
						 | 
				
			
			@ -35,6 +35,8 @@ mut:
 | 
			
		|||
	// checked_ident  string // to avoid infinit checker loops
 | 
			
		||||
	var_decl_name  string
 | 
			
		||||
	returns        bool
 | 
			
		||||
	mod string  // current module name
 | 
			
		||||
	is_builtin_mod bool // are we in `builtin`?
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn new_checker(table &table.Table, pref &pref.Preferences) Checker {
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +152,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
 | 
			
		|||
						}
 | 
			
		||||
					}
 | 
			
		||||
					if !exists {
 | 
			
		||||
						c.error('struct init: no such field `$field.name` for struct `$type_sym.name`', field.pos)
 | 
			
		||||
						c.error('unknown field `$field.name` in struct literal of type `$type_sym.name`', field.pos)
 | 
			
		||||
						continue
 | 
			
		||||
					}
 | 
			
		||||
					if field_name in inited_fields {
 | 
			
		||||
| 
						 | 
				
			
			@ -320,6 +322,12 @@ pub fn (c mut Checker) call_method(call_expr mut ast.CallExpr) table.Type {
 | 
			
		|||
		return info.elem_type
 | 
			
		||||
	}
 | 
			
		||||
	if method := c.table.type_find_method(left_type_sym, method_name) {
 | 
			
		||||
		if !method.is_pub && !c.is_builtin_mod && left_type_sym.mod != c.mod && left_type_sym.mod != '' { // method.mod != c.mod {
 | 
			
		||||
			// If a private method is called outside of the module
 | 
			
		||||
			// its receiver type is defined in, show an error.
 | 
			
		||||
			//println('warn $method_name lef.mod=$left_type_sym.mod c.mod=$c.mod')
 | 
			
		||||
			c.error('method `${left_type_sym.name}.$method_name` is private', call_expr.pos)
 | 
			
		||||
		}
 | 
			
		||||
		no_args := method.args.len - 1
 | 
			
		||||
		min_required_args := method.args.len - if method.is_variadic && method.args.len > 1 { 2 } else { 1 }
 | 
			
		||||
		if call_expr.args.len < min_required_args {
 | 
			
		||||
| 
						 | 
				
			
			@ -1012,6 +1020,11 @@ fn (c mut Checker) stmt(node ast.Stmt) {
 | 
			
		|||
		}
 | 
			
		||||
		// ast.HashStmt {}
 | 
			
		||||
		ast.Import {}
 | 
			
		||||
		ast.Module {
 | 
			
		||||
			c.mod = it.name
 | 
			
		||||
			c.is_builtin_mod = it.name == 'builtin'
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// ast.GlobalDecl {}
 | 
			
		||||
		ast.Return {
 | 
			
		||||
			c.returns = true
 | 
			
		||||
| 
						 | 
				
			
			@ -1635,7 +1648,14 @@ fn (c mut Checker) warn_or_error(message string, pos token.Position, warn bool)
 | 
			
		|||
	// if c.pref.is_verbose {
 | 
			
		||||
	// print_backtrace()
 | 
			
		||||
	// }
 | 
			
		||||
	if !warn {
 | 
			
		||||
	if warn {
 | 
			
		||||
		c.warnings << scanner.Warning{
 | 
			
		||||
			reporter: scanner.Reporter.checker
 | 
			
		||||
			pos: pos
 | 
			
		||||
			file_path: c.file.path
 | 
			
		||||
			message: message
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		c.nr_errors++
 | 
			
		||||
		if !(pos.line_nr in c.error_lines) {
 | 
			
		||||
			c.errors << scanner.Error{
 | 
			
		||||
| 
						 | 
				
			
			@ -1646,16 +1666,10 @@ fn (c mut Checker) warn_or_error(message string, pos token.Position, warn bool)
 | 
			
		|||
			}
 | 
			
		||||
			c.error_lines << pos.line_nr
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		c.warnings << scanner.Warning{
 | 
			
		||||
			reporter: scanner.Reporter.checker
 | 
			
		||||
			pos: pos
 | 
			
		||||
			file_path: c.file.path
 | 
			
		||||
			message: message
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// for debugging only
 | 
			
		||||
fn (p Checker) fileis(s string) bool {
 | 
			
		||||
	return p.file.path.contains(s)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,7 +1,7 @@
 | 
			
		|||
vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: struct init: no such field `bar` for struct `Test`
 | 
			
		||||
vlib/v/checker/tests/inout/struct_unknown_field.v:8:9: error: unknown field `bar` in struct literal `Test`
 | 
			
		||||
    6|     t := Test{
 | 
			
		||||
    7|         foo: true
 | 
			
		||||
    8|         bar: false
 | 
			
		||||
               ^
 | 
			
		||||
    9|     }
 | 
			
		||||
   10| }
 | 
			
		||||
   10| }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -180,6 +180,7 @@ fn (var p Parser) fn_decl() ast.FnDecl {
 | 
			
		|||
			return_type: return_type
 | 
			
		||||
			is_variadic: is_variadic
 | 
			
		||||
			is_generic: is_generic
 | 
			
		||||
			is_pub: is_pub
 | 
			
		||||
		})
 | 
			
		||||
	} else {
 | 
			
		||||
		if is_c {
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +201,7 @@ fn (var p Parser) fn_decl() ast.FnDecl {
 | 
			
		|||
			is_c: is_c
 | 
			
		||||
			is_js: is_js
 | 
			
		||||
			is_generic: is_generic
 | 
			
		||||
			is_pub: is_pub
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
	// Body
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,8 +26,8 @@ mut:
 | 
			
		|||
	inside_for        bool
 | 
			
		||||
	inside_fn         bool
 | 
			
		||||
	pref              &pref.Preferences
 | 
			
		||||
	builtin_mod       bool
 | 
			
		||||
	mod               string
 | 
			
		||||
	builtin_mod       bool // are we in the `builtin` module?
 | 
			
		||||
	mod               string // current module name
 | 
			
		||||
	attr              string
 | 
			
		||||
	expr_mod          string
 | 
			
		||||
	scope             &ast.Scope
 | 
			
		||||
| 
						 | 
				
			
			@ -1690,6 +1690,7 @@ fn (var p Parser) struct_decl() ast.StructDecl {
 | 
			
		|||
			is_typedef: is_typedef
 | 
			
		||||
			is_union: is_union
 | 
			
		||||
		}
 | 
			
		||||
		mod: p.mod
 | 
			
		||||
	}
 | 
			
		||||
	var ret := 0
 | 
			
		||||
	if p.builtin_mod && t.name in table.builtin_type_names {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,10 +11,8 @@
 | 
			
		|||
// idx:  u16(type) & 0xffff
 | 
			
		||||
module table
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	strings
 | 
			
		||||
	v.ast
 | 
			
		||||
)
 | 
			
		||||
import strings
 | 
			
		||||
import v.ast
 | 
			
		||||
 | 
			
		||||
pub type Type int
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -28,6 +26,7 @@ mut:
 | 
			
		|||
	kind       Kind
 | 
			
		||||
	name       string
 | 
			
		||||
	methods    []Fn
 | 
			
		||||
	mod        string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub enum TypeFlag {
 | 
			
		||||
| 
						 | 
				
			
			@ -310,7 +309,7 @@ pub fn (t TypeSymbol) str() string {
 | 
			
		|||
	return t.name
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
pub fn (t mut Table) register_builtin_type_symbols() {
 | 
			
		||||
pub fn (var t Table) register_builtin_type_symbols() {
 | 
			
		||||
	// reserve index 0 so nothing can go there
 | 
			
		||||
	// save index check, 0 will mean not found
 | 
			
		||||
	t.register_type_symbol(TypeSymbol{
 | 
			
		||||
| 
						 | 
				
			
			@ -527,7 +526,7 @@ pub fn (k Kind) str() string {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub fn (kinds []Kind) str() string {
 | 
			
		||||
	mut kinds_str := ''
 | 
			
		||||
	var kinds_str := ''
 | 
			
		||||
	for i, k in kinds {
 | 
			
		||||
		kinds_str += k.str()
 | 
			
		||||
		if i < kinds.len - 1 {
 | 
			
		||||
| 
						 | 
				
			
			@ -594,7 +593,7 @@ pub:
 | 
			
		|||
pub fn (table &Table) type_to_str(t Type) string {
 | 
			
		||||
	sym := table.get_type_symbol(t)
 | 
			
		||||
	if sym.kind == .multi_return {
 | 
			
		||||
		mut res := '('
 | 
			
		||||
		var res := '('
 | 
			
		||||
		mr_info := sym.info as MultiReturn
 | 
			
		||||
		for i, typ in mr_info.types {
 | 
			
		||||
			res += table.type_to_str(typ)
 | 
			
		||||
| 
						 | 
				
			
			@ -605,7 +604,7 @@ pub fn (table &Table) type_to_str(t Type) string {
 | 
			
		|||
		res += ')'
 | 
			
		||||
		return res
 | 
			
		||||
	}
 | 
			
		||||
	mut res := sym.name
 | 
			
		||||
	var res := sym.name
 | 
			
		||||
	if sym.kind == .array {
 | 
			
		||||
		res = res.replace('array_', '[]')
 | 
			
		||||
	} else if sym.kind == .map {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,15 +17,15 @@ fn (table &Table) has_cflag(cflag builder.CFlag) bool {
 | 
			
		|||
 | 
			
		||||
// parse the flags to (table.cflags) []CFlag
 | 
			
		||||
// Note: clean up big time (joe-c)
 | 
			
		||||
fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool {
 | 
			
		||||
pub fn (var table Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool {
 | 
			
		||||
	allowed_flags := ['framework', 'library', 'Wa', 'Wl', 'Wp', 'I', 'l', 'L']
 | 
			
		||||
	flag_orig := cflag.trim_space()
 | 
			
		||||
	mut flag := flag_orig
 | 
			
		||||
	var flag := flag_orig
 | 
			
		||||
	if flag == '' {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	mut fos := ''
 | 
			
		||||
	mut allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris']
 | 
			
		||||
	var fos := ''
 | 
			
		||||
	var allowed_os_overrides := ['linux', 'darwin', 'freebsd', 'windows', 'mingw', 'solaris']
 | 
			
		||||
	allowed_os_overrides << ctimedefines
 | 
			
		||||
	for os_override in allowed_os_overrides {
 | 
			
		||||
		if !flag.starts_with(os_override) {
 | 
			
		||||
| 
						 | 
				
			
			@ -37,9 +37,9 @@ fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool
 | 
			
		|||
		fos = flag[..pos].trim_space()
 | 
			
		||||
		flag = flag[pos..].trim_space()
 | 
			
		||||
	}
 | 
			
		||||
	for  {
 | 
			
		||||
		mut name := ''
 | 
			
		||||
		mut value := ''
 | 
			
		||||
	for {
 | 
			
		||||
		var name := ''
 | 
			
		||||
		var value := ''
 | 
			
		||||
		if flag[0] == `-` {
 | 
			
		||||
			for f in allowed_flags {
 | 
			
		||||
				i := 1 + f.len
 | 
			
		||||
| 
						 | 
				
			
			@ -50,11 +50,11 @@ fn (table mut Table) parse_cflag(cflag, mod string, ctimedefines []string) ?bool
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		mut index := flag.index(' -') or {
 | 
			
		||||
		var index := flag.index(' -') or {
 | 
			
		||||
			-1
 | 
			
		||||
		}
 | 
			
		||||
		for index > -1 {
 | 
			
		||||
			mut has_next := false
 | 
			
		||||
			var has_next := false
 | 
			
		||||
			for f in allowed_flags {
 | 
			
		||||
				i := index + 2 + f.len
 | 
			
		||||
				if i <= flag.len && f == flag[index + 2..i] {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,10 +3,8 @@
 | 
			
		|||
// that can be found in the LICENSE file.
 | 
			
		||||
module table
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	os
 | 
			
		||||
	v.builder
 | 
			
		||||
)
 | 
			
		||||
import os
 | 
			
		||||
import v.builder
 | 
			
		||||
 | 
			
		||||
pub struct Table {
 | 
			
		||||
pub mut:
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +23,10 @@ pub:
 | 
			
		|||
	return_type Type
 | 
			
		||||
	is_variadic bool
 | 
			
		||||
	is_c        bool
 | 
			
		||||
	is_js		bool
 | 
			
		||||
	is_js       bool
 | 
			
		||||
	is_generic  bool
 | 
			
		||||
	is_pub      bool
 | 
			
		||||
	mod         string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct Arg {
 | 
			
		||||
| 
						 | 
				
			
			@ -45,14 +45,14 @@ mut:
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
pub fn new_table() &Table {
 | 
			
		||||
	mut t := &Table{}
 | 
			
		||||
	var t := &Table{}
 | 
			
		||||
	t.register_builtin_type_symbols()
 | 
			
		||||
	return t
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// used to compare fn's & for naming anon fn's
 | 
			
		||||
pub fn (f &Fn) signature() string {
 | 
			
		||||
	mut sig := ''
 | 
			
		||||
	var sig := ''
 | 
			
		||||
	for i, arg in f.args {
 | 
			
		||||
		// TODO: for now ignore mut/pts in sig for now
 | 
			
		||||
		typ := type_set_nr_muls(arg.typ, 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -85,12 +85,12 @@ pub fn (t &Table) known_fn(name string) bool {
 | 
			
		|||
	return true
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) register_fn(new_fn Fn) {
 | 
			
		||||
pub fn (var t Table) register_fn(new_fn Fn) {
 | 
			
		||||
	// println('reg fn $new_fn.name nr_args=$new_fn.args.len')
 | 
			
		||||
	t.fns[new_fn.name] = new_fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut TypeSymbol) register_method(new_fn Fn) {
 | 
			
		||||
pub fn (var t TypeSymbol) register_method(new_fn Fn) {
 | 
			
		||||
	t.methods << new_fn
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -142,7 +142,7 @@ pub fn (t &Table) type_has_method(s &TypeSymbol, name string) bool {
 | 
			
		|||
// search from current type up through each parent looking for method
 | 
			
		||||
pub fn (t &Table) type_find_method(s &TypeSymbol, name string) ?Fn {
 | 
			
		||||
	// println('type_find_method($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
 | 
			
		||||
	mut ts := s
 | 
			
		||||
	var ts := s
 | 
			
		||||
	for {
 | 
			
		||||
		if method := ts.find_method(name) {
 | 
			
		||||
			return method
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +166,7 @@ pub fn (t &Table) struct_has_field(s &TypeSymbol, name string) bool {
 | 
			
		|||
// search from current type up through each parent looking for field
 | 
			
		||||
pub fn (t &Table) struct_find_field(s &TypeSymbol, name string) ?Field {
 | 
			
		||||
	// println('struct_find_field($s.name, $name) types.len=$t.types.len s.parent_idx=$s.parent_idx')
 | 
			
		||||
	mut ts := s
 | 
			
		||||
	var ts := s
 | 
			
		||||
	for {
 | 
			
		||||
		if field := ts.find_field(name) {
 | 
			
		||||
			return field
 | 
			
		||||
| 
						 | 
				
			
			@ -210,12 +210,11 @@ pub fn (t &Table) get_type_name(typ Type) string {
 | 
			
		|||
	return typ_sym.name
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// this will override or register builtin type
 | 
			
		||||
// allows prexisitng types added in register_builtins
 | 
			
		||||
// to be overriden with their real type info
 | 
			
		||||
[inline]
 | 
			
		||||
pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int {
 | 
			
		||||
pub fn (var t Table) register_builtin_type_symbol(typ TypeSymbol) int {
 | 
			
		||||
	existing_idx := t.type_idxs[typ.name]
 | 
			
		||||
	if existing_idx > 0 {
 | 
			
		||||
		if existing_idx >= string_type_idx {
 | 
			
		||||
| 
						 | 
				
			
			@ -235,7 +234,7 @@ pub fn (t mut Table) register_builtin_type_symbol(typ TypeSymbol) int {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
[inline]
 | 
			
		||||
pub fn (t mut Table) register_type_symbol(typ TypeSymbol) int {
 | 
			
		||||
pub fn (var t Table) register_type_symbol(typ TypeSymbol) int {
 | 
			
		||||
	// println('register_type_symbol( $typ.name )')
 | 
			
		||||
	existing_idx := t.type_idxs[typ.name]
 | 
			
		||||
	if existing_idx > 0 {
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +308,7 @@ pub fn (t &Table) map_name(key_type, value_type Type) string {
 | 
			
		|||
	// return 'map_${value_type_sym.name}' + suffix
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int {
 | 
			
		||||
pub fn (var t Table) find_or_register_map(key_type, value_type Type) int {
 | 
			
		||||
	name := t.map_name(key_type, value_type)
 | 
			
		||||
	// existing
 | 
			
		||||
	existing_idx := t.type_idxs[name]
 | 
			
		||||
| 
						 | 
				
			
			@ -329,7 +328,7 @@ pub fn (t mut Table) find_or_register_map(key_type, value_type Type) int {
 | 
			
		|||
	return t.register_type_symbol(map_typ)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int {
 | 
			
		||||
pub fn (var t Table) find_or_register_array(elem_type Type, nr_dims int) int {
 | 
			
		||||
	name := t.array_name(elem_type, nr_dims)
 | 
			
		||||
	// existing
 | 
			
		||||
	existing_idx := t.type_idxs[name]
 | 
			
		||||
| 
						 | 
				
			
			@ -349,7 +348,7 @@ pub fn (t mut Table) find_or_register_array(elem_type Type, nr_dims int) int {
 | 
			
		|||
	return t.register_type_symbol(array_type)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size, nr_dims int) int {
 | 
			
		||||
pub fn (var t Table) find_or_register_array_fixed(elem_type Type, size, nr_dims int) int {
 | 
			
		||||
	name := t.array_fixed_name(elem_type, size, nr_dims)
 | 
			
		||||
	// existing
 | 
			
		||||
	existing_idx := t.type_idxs[name]
 | 
			
		||||
| 
						 | 
				
			
			@ -369,8 +368,8 @@ pub fn (t mut Table) find_or_register_array_fixed(elem_type Type, size, nr_dims
 | 
			
		|||
	return t.register_type_symbol(array_fixed_type)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int {
 | 
			
		||||
	mut name := 'multi_return'
 | 
			
		||||
pub fn (var t Table) find_or_register_multi_return(mr_typs []Type) int {
 | 
			
		||||
	var name := 'multi_return'
 | 
			
		||||
	for mr_typ in mr_typs {
 | 
			
		||||
		mr_type_sym := t.get_type_symbol(mr_typ)
 | 
			
		||||
		name += '_$mr_type_sym.name'
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +390,7 @@ pub fn (t mut Table) find_or_register_multi_return(mr_typs []Type) int {
 | 
			
		|||
	return t.register_type_symbol(mr_type)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) find_or_register_fn_type(f Fn, has_decl bool) int {
 | 
			
		||||
pub fn (var t Table) find_or_register_fn_type(f Fn, has_decl bool) int {
 | 
			
		||||
	is_anon := f.name.len == 0
 | 
			
		||||
	name := if is_anon { 'anon_fn_$f.signature()' } else { f.name }
 | 
			
		||||
	return t.register_type_symbol(TypeSymbol{
 | 
			
		||||
| 
						 | 
				
			
			@ -405,7 +404,7 @@ pub fn (t mut Table) find_or_register_fn_type(f Fn, has_decl bool) int {
 | 
			
		|||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub fn (t mut Table) add_placeholder_type(name string) int {
 | 
			
		||||
pub fn (var t Table) add_placeholder_type(name string) int {
 | 
			
		||||
	ph_type := TypeSymbol{
 | 
			
		||||
		kind: .placeholder
 | 
			
		||||
		name: name
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue