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) | fn C.backtrace_symbols_fd(a &voidptr, size int, fd int) | ||||||
| 
 | 
 | ||||||
| // <libproc.h>
 | // <libproc.h>
 | ||||||
| fn proc_pidpath(int, voidptr, int) int | pub fn proc_pidpath(int, voidptr, int) int | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.realpath(byteptr, byteptr) &char | fn C.realpath(byteptr, byteptr) &char | ||||||
|  |  | ||||||
|  | @ -836,7 +836,7 @@ pub fn on_segfault(f voidptr) { | ||||||
| fn C.getpid() int | fn C.getpid() int | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.proc_pidpath(int, byteptr, int) int | //fn C.proc_pidpath(int, byteptr, int) int
 | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.readlink() int | fn C.readlink() int | ||||||
|  |  | ||||||
|  | @ -12,7 +12,7 @@ const ( | ||||||
| 	max_u64 = u64(C.UINT64_MAX)// as u64 // use this until we add support
 | 	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`) | 	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`
 | // the first arg is defined in include/bits/types.h as `__S32_TYPE`, which is `int`
 | ||||||
| fn C.clock_gettime(int, &C.timespec) | fn C.clock_gettime(int, &C.timespec) | ||||||
| 
 | 
 | ||||||
| fn sys_mono_now() u64 { | pub fn sys_mono_now() u64 { | ||||||
| 	$if macos { | 	$if macos { | ||||||
| 		return sys_mono_now_darwin() | 		return sys_mono_now_darwin() | ||||||
| 	} $else { | 	} $else { | ||||||
|  |  | ||||||
|  | @ -41,7 +41,7 @@ fn init_win_time_start() u64 { | ||||||
| 	return s | 	return s | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn sys_mono_now() u64 { | pub fn sys_mono_now() u64 { | ||||||
| 	tm := u64(0) | 	tm := u64(0) | ||||||
| 	C.QueryPerformanceCounter(&tm) // XP or later never fail
 | 	C.QueryPerformanceCounter(&tm) // XP or later never fail
 | ||||||
| 	return (tm - start_time) * 1_000_000_000 / freq_time | 	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) | 				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 | 	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 { | 	if f.return_type == table.void_type && f.ctdefine.len > 0 && f.ctdefine !in c.pref.compile_defines { | ||||||
| 		call_expr.should_be_skipped = true | 		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) | 			c.check_expr_opt_call(it.expr, etype, false) | ||||||
| 		} | 		} | ||||||
| 		ast.FnDecl { | 		ast.FnDecl { | ||||||
| 			if !it.is_c && !it.is_js && !c.is_builtin_mod { | 			c.fn_decl(it) | ||||||
| 				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 |  | ||||||
| 		} | 		} | ||||||
| 		ast.ForCStmt { | 		ast.ForCStmt { | ||||||
| 			c.in_for_count++ | 			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 { | fn (c &Checker) fileis(s string) bool { | ||||||
| 	return c.file.path.contains(s) | 	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_generic: is_generic | ||||||
| 			is_pub: is_pub | 			is_pub: is_pub | ||||||
| 			ctdefine: ctdefine | 			ctdefine: ctdefine | ||||||
|  | 			mod: p.mod | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| 	// Body
 | 	// Body
 | ||||||
|  |  | ||||||
|  | @ -3,21 +3,21 @@ module util | ||||||
| import os | import os | ||||||
| 
 | 
 | ||||||
| [inline] | [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 == `_` | 	return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [inline] | [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() | 	return (c >= `a` && c <= `z`) || (c >= `A` && c <= `Z`) || c == `_` || c.is_digit() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [inline] | [inline] | ||||||
| fn is_nl(c byte) bool { | pub fn is_nl(c byte) bool { | ||||||
| 	return c == `\r` || c == `\n` | 	return c == `\r` || c == `\n` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn contains_capital(s string) bool { | pub fn contains_capital(s string) bool { | ||||||
| 	for c in s { | 	for c in s { | ||||||
| 		if c >= `A` && c <= `Z` { | 		if c >= `A` && c <= `Z` { | ||||||
| 			return true | 			return true | ||||||
|  | @ -28,7 +28,7 @@ fn contains_capital(s string) bool { | ||||||
| 
 | 
 | ||||||
| // HTTPRequest  bad
 | // HTTPRequest  bad
 | ||||||
| // HttpRequest  good
 | // HttpRequest  good
 | ||||||
| fn good_type_name(s string) bool { | pub fn good_type_name(s string) bool { | ||||||
| 	if s.len < 4 { | 	if s.len < 4 { | ||||||
| 		return true | 		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] | 	last_char := s[s.len - 1] | ||||||
| 	suffix := match last_char { | 	suffix := match last_char { | ||||||
| 		`+` { '_plus' } | 		`+` { '_plus' } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue