parser: do not allow calling private functions
							parent
							
								
									2a62f1a312
								
							
						
					
					
						commit
						03525843a0
					
				|  | @ -31,7 +31,7 @@ fn C.backtrace_symbols(a &voidptr, size int)  &charptr | |||
| fn C.backtrace_symbols_fd(a &voidptr, size int, fd int) | ||||
| 
 | ||||
| // <libproc.h>
 | ||||
| fn proc_pidpath(int, voidptr, int) int | ||||
| pub fn proc_pidpath(int, voidptr, int) int | ||||
| 
 | ||||
| 
 | ||||
| fn C.realpath(byteptr, byteptr) &char | ||||
|  |  | |||
|  | @ -836,7 +836,7 @@ pub fn on_segfault(f voidptr) { | |||
| fn C.getpid() int | ||||
| 
 | ||||
| 
 | ||||
| fn C.proc_pidpath(int, byteptr, int) int | ||||
| //fn C.proc_pidpath(int, byteptr, int) int
 | ||||
| 
 | ||||
| 
 | ||||
| fn C.readlink() int | ||||
|  |  | |||
|  | @ -12,7 +12,7 @@ const ( | |||
| 	max_u64 = u64(C.UINT64_MAX)// as u64 // use this until we add support
 | ||||
| ) | ||||
| 
 | ||||
| fn byte_to_lower(c byte) byte { | ||||
| pub fn byte_to_lower(c byte) byte { | ||||
| 	return c | (`x` - `X`) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -29,7 +29,7 @@ struct C.timespec { | |||
| // the first arg is defined in include/bits/types.h as `__S32_TYPE`, which is `int`
 | ||||
| fn C.clock_gettime(int, &C.timespec) | ||||
| 
 | ||||
| fn sys_mono_now() u64 { | ||||
| pub fn sys_mono_now() u64 { | ||||
| 	$if macos { | ||||
| 		return sys_mono_now_darwin() | ||||
| 	} $else { | ||||
|  |  | |||
|  | @ -41,7 +41,7 @@ fn init_win_time_start() u64 { | |||
| 	return s | ||||
| } | ||||
| 
 | ||||
| fn sys_mono_now() u64 { | ||||
| pub fn sys_mono_now() u64 { | ||||
| 	tm := u64(0) | ||||
| 	C.QueryPerformanceCounter(&tm) // XP or later never fail
 | ||||
| 	return (tm - start_time) * 1_000_000_000 / freq_time | ||||
|  |  | |||
|  | @ -878,6 +878,10 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { | |||
| 				call_expr.pos) | ||||
| 		} | ||||
| 	} | ||||
| 	if !f.is_pub && !f.is_c && !c.is_builtin_mod && !c.pref.is_test && f.mod != c.mod && f.name != | ||||
| 		'' && f.mod != '' { | ||||
| 		c.warn('function `$f.name` is private. curmod=$c.mod fmod=$f.mod', call_expr.pos) | ||||
| 	} | ||||
| 	call_expr.return_type = f.return_type | ||||
| 	if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines { | ||||
| 		call_expr.should_be_skipped = true | ||||
|  | @ -1483,35 +1487,7 @@ fn (mut c Checker) stmt(node ast.Stmt) { | |||
| 			c.check_expr_opt_call(it.expr, etype, false) | ||||
| 		} | ||||
| 		ast.FnDecl { | ||||
| 			if !it.is_c && !it.is_js && !c.is_builtin_mod { | ||||
| 				c.check_valid_snake_case(it.name, 'function name', it.pos) | ||||
| 			} | ||||
| 			if it.is_method { | ||||
| 				sym := c.table.get_type_symbol(it.receiver.typ) | ||||
| 				if sym.kind == .interface_ { | ||||
| 					c.error('interfaces cannot be used as method receiver', it.receiver_pos) | ||||
| 				} | ||||
| 				// if sym.has_method(it.name) {
 | ||||
| 				// c.warn('duplicate method `$it.name`', it.pos)
 | ||||
| 				// }
 | ||||
| 			} | ||||
| 			if !it.is_c { | ||||
| 				// Make sure all types are valid
 | ||||
| 				for arg in it.args { | ||||
| 					sym := c.table.get_type_symbol(arg.typ) | ||||
| 					if sym.kind == .placeholder { | ||||
| 						c.error('unknown type `$sym.name`', it.pos) | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			c.expected_type = table.void_type | ||||
| 			c.fn_return_type = it.return_type | ||||
| 			c.stmts(it.stmts) | ||||
| 			if !it.is_c && !it.is_js && !it.no_body && it.return_type != table.void_type && | ||||
| 				!c.returns && it.name !in ['panic', 'exit'] { | ||||
| 				c.error('missing return at end of function `$it.name`', it.pos) | ||||
| 			} | ||||
| 			c.returns = false | ||||
| 			c.fn_decl(it) | ||||
| 		} | ||||
| 		ast.ForCStmt { | ||||
| 			c.in_for_count++ | ||||
|  | @ -2312,3 +2288,35 @@ fn (mut c Checker) warn_or_error(message string, pos token.Position, warn bool) | |||
| fn (c &Checker) fileis(s string) bool { | ||||
| 	return c.file.path.contains(s) | ||||
| } | ||||
| 
 | ||||
| fn (mut c Checker) fn_decl(it ast.FnDecl) { | ||||
| 	if !it.is_c && !it.is_js && !c.is_builtin_mod { | ||||
| 		c.check_valid_snake_case(it.name, 'function name', it.pos) | ||||
| 	} | ||||
| 	if it.is_method { | ||||
| 		sym := c.table.get_type_symbol(it.receiver.typ) | ||||
| 		if sym.kind == .interface_ { | ||||
| 			c.error('interfaces cannot be used as method receiver', it.receiver_pos) | ||||
| 		} | ||||
| 		// if sym.has_method(it.name) {
 | ||||
| 		// c.warn('duplicate method `$it.name`', it.pos)
 | ||||
| 		// }
 | ||||
| 	} | ||||
| 	if !it.is_c { | ||||
| 		// Make sure all types are valid
 | ||||
| 		for arg in it.args { | ||||
| 			sym := c.table.get_type_symbol(arg.typ) | ||||
| 			if sym.kind == .placeholder { | ||||
| 				c.error('unknown type `$sym.name`', it.pos) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	c.expected_type = table.void_type | ||||
| 	c.fn_return_type = it.return_type | ||||
| 	c.stmts(it.stmts) | ||||
| 	if !it.is_c && !it.is_js && !it.no_body && it.return_type != table.void_type && !c.returns && | ||||
| 		it.name !in ['panic', 'exit'] { | ||||
| 		c.error('missing return at end of function `$it.name`', it.pos) | ||||
| 	} | ||||
| 	c.returns = false | ||||
| } | ||||
|  |  | |||
|  | @ -255,6 +255,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { | |||
| 			is_generic: is_generic | ||||
| 			is_pub: is_pub | ||||
| 			ctdefine: ctdefine | ||||
| 			mod: p.mod | ||||
| 		}) | ||||
| 	} | ||||
| 	// Body
 | ||||
|  |  | |||
|  | @ -3,21 +3,21 @@ module util | |||
| import os | ||||
| 
 | ||||
| [inline] | ||||
| fn is_name_char(c byte) bool { | ||||
| pub fn is_name_char(c byte) bool { | ||||
| 	return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| fn is_func_char(c byte) bool { | ||||
| pub fn is_func_char(c byte) bool { | ||||
| 	return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` || c.is_digit() | ||||
| } | ||||
| 
 | ||||
| [inline] | ||||
| fn is_nl(c byte) bool { | ||||
| pub fn is_nl(c byte) bool { | ||||
| 	return c == `\r` || c == `\n` | ||||
| } | ||||
| 
 | ||||
| fn contains_capital(s string) bool { | ||||
| pub fn contains_capital(s string) bool { | ||||
| 	for c in s { | ||||
| 		if c >= `A` && c <= `Z` { | ||||
| 			return true | ||||
|  | @ -28,7 +28,7 @@ fn contains_capital(s string) bool { | |||
| 
 | ||||
| // HTTPRequest  bad
 | ||||
| // HttpRequest  good
 | ||||
| fn good_type_name(s string) bool { | ||||
| pub fn good_type_name(s string) bool { | ||||
| 	if s.len < 4 { | ||||
| 		return true | ||||
| 	} | ||||
|  |  | |||
|  | @ -222,7 +222,7 @@ fn imax(a, b int) int { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| fn replace_op(s string) string { | ||||
| pub fn replace_op(s string) string { | ||||
| 	last_char := s[s.len - 1] | ||||
| 	suffix := match last_char { | ||||
| 		`+` { '_plus' } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue