checker: check number of C function arguments for some cases (#8444)
							parent
							
								
									2cadb3e4d8
								
							
						
					
					
						commit
						64d12cdc8d
					
				|  | @ -7,7 +7,7 @@ fn C.memcmp(byteptr, byteptr, int) int | ||||||
| 
 | 
 | ||||||
| fn C.memmove(byteptr, byteptr, int) voidptr | fn C.memmove(byteptr, byteptr, int) voidptr | ||||||
| 
 | 
 | ||||||
| fn C.calloc(int) byteptr | fn C.calloc(int, int) byteptr | ||||||
| 
 | 
 | ||||||
| fn C.malloc(int) byteptr | fn C.malloc(int) byteptr | ||||||
| 
 | 
 | ||||||
|  | @ -48,16 +48,16 @@ fn C.printf(byteptr, ...byteptr) int | ||||||
| 
 | 
 | ||||||
| fn C.puts(byteptr) int | fn C.puts(byteptr) int | ||||||
| 
 | 
 | ||||||
| fn C.fputs(byteptr) int | fn C.fputs(str byteptr, stream &C.FILE) int | ||||||
| 
 | 
 | ||||||
| fn C.fflush(byteptr) int | fn C.fflush(&C.FILE) int | ||||||
| 
 | 
 | ||||||
| // TODO define args in these functions
 | // TODO define args in these functions
 | ||||||
| fn C.fseek() int | fn C.fseek() int | ||||||
| 
 | 
 | ||||||
| fn C.fopen() voidptr | fn C.fopen(filename charptr, mode charptr) &C.FILE | ||||||
| 
 | 
 | ||||||
| fn C.fileno(voidptr) int | fn C.fileno(&C.FILE) int | ||||||
| 
 | 
 | ||||||
| fn C.fread(ptr voidptr, item_size size_t, items size_t, stream &C.FILE) size_t | fn C.fread(ptr voidptr, item_size size_t, items size_t, stream &C.FILE) size_t | ||||||
| 
 | 
 | ||||||
|  | @ -86,7 +86,7 @@ fn C.waitpid(pid int, status &int, options int) int | ||||||
| 
 | 
 | ||||||
| fn C.kill(pid int, sig int) int | fn C.kill(pid int, sig int) int | ||||||
| 
 | 
 | ||||||
| fn C.setenv(charptr) int | fn C.setenv(charptr, charptr, int) int | ||||||
| 
 | 
 | ||||||
| fn C.unsetenv(charptr) int | fn C.unsetenv(charptr) int | ||||||
| 
 | 
 | ||||||
|  | @ -100,7 +100,7 @@ fn C.chdir() int | ||||||
| 
 | 
 | ||||||
| fn C.rewind() int | fn C.rewind() int | ||||||
| 
 | 
 | ||||||
| fn C.stat(charptr) int | fn C.stat(charptr, voidptr) int | ||||||
| 
 | 
 | ||||||
| fn C.lstat() int | fn C.lstat() int | ||||||
| 
 | 
 | ||||||
|  | @ -125,7 +125,7 @@ fn C.sleep(int) int | ||||||
| 
 | 
 | ||||||
| fn C.usleep() int | fn C.usleep() int | ||||||
| 
 | 
 | ||||||
| fn C.opendir() voidptr | fn C.opendir(charptr) voidptr | ||||||
| 
 | 
 | ||||||
| fn C.closedir() int | fn C.closedir() int | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -105,22 +105,22 @@ fn decode_string(root &C.cJSON) string { | ||||||
| 	return tos_clone(root.valuestring) // , _strlen(root.valuestring))
 | 	return tos_clone(root.valuestring) // , _strlen(root.valuestring))
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_IsTrue() bool | fn C.cJSON_IsTrue(voidptr) bool | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_CreateNumber() &C.cJSON | fn C.cJSON_CreateNumber(int) &C.cJSON | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_CreateBool() &C.cJSON | fn C.cJSON_CreateBool(bool) &C.cJSON | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_CreateString() &C.cJSON | fn C.cJSON_CreateString(charptr) &C.cJSON | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_Parse() &C.cJSON | fn C.cJSON_Parse(charptr) &C.cJSON | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn C.cJSON_PrintUnformatted() byteptr | fn C.cJSON_PrintUnformatted(voidptr) byteptr | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| fn decode_bool(root &C.cJSON) bool { | fn decode_bool(root &C.cJSON) bool { | ||||||
|  |  | ||||||
|  | @ -16,7 +16,7 @@ fn C.ftell(fp voidptr) int | ||||||
| 
 | 
 | ||||||
| fn C.sigaction(int, voidptr, int) | fn C.sigaction(int, voidptr, int) | ||||||
| 
 | 
 | ||||||
| fn C.open(charptr, int, int) int | fn C.open(charptr, int, ...int) int | ||||||
| 
 | 
 | ||||||
| fn C.fdopen(int, string) voidptr | fn C.fdopen(int, string) voidptr | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1781,6 +1781,15 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type { | ||||||
| 		call_expr.should_be_skipped = true | 		call_expr.should_be_skipped = true | ||||||
| 	} | 	} | ||||||
| 	if f.language != .v || call_expr.language != .v { | 	if f.language != .v || call_expr.language != .v { | ||||||
|  | 		// ignore C function of type `fn()`, assume untyped
 | ||||||
|  | 		// For now don't check C functions that are variadic, underscored, capitalized
 | ||||||
|  | 		// or have no params and return int
 | ||||||
|  | 		if f.language == .c && f.params.len != call_expr.args.len && !f.is_variadic | ||||||
|  | 			&& f.name[2] != `_` && !f.name[2].is_capital() | ||||||
|  | 			&& (f.params.len != 0 || f.return_type !in [table.void_type, table.int_type]) { | ||||||
|  | 			// change to error later
 | ||||||
|  | 			c.warn('expected $f.params.len arguments, but got $call_expr.args.len', call_expr.pos) | ||||||
|  | 		} | ||||||
| 		for arg in call_expr.args { | 		for arg in call_expr.args { | ||||||
| 			c.expr(arg.expr) | 			c.expr(arg.expr) | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -0,0 +1,27 @@ | ||||||
|  | vlib/v/checker/tests/c_fn_surplus_args.vv:7:4: error: expected 1 arguments, but got 0 | ||||||
|  |     5 | fn main() { | ||||||
|  |     6 |     C.no(1) // allowed | ||||||
|  |     7 |     C.y1() | ||||||
|  |       |       ~~~~ | ||||||
|  |     8 |     C.y1(1) // ok | ||||||
|  |     9 |     C.y1(1, 2) | ||||||
|  | vlib/v/checker/tests/c_fn_surplus_args.vv:9:4: error: expected 1 arguments, but got 2 | ||||||
|  |     7 |     C.y1() | ||||||
|  |     8 |     C.y1(1) // ok | ||||||
|  |     9 |     C.y1(1, 2) | ||||||
|  |       |       ~~~~~~~~ | ||||||
|  |    10 |     C.ret() // ok | ||||||
|  |    11 |     C.ret(1) | ||||||
|  | vlib/v/checker/tests/c_fn_surplus_args.vv:11:4: error: expected 0 arguments, but got 1 | ||||||
|  |     9 |     C.y1(1, 2) | ||||||
|  |    10 |     C.ret() // ok | ||||||
|  |    11 |     C.ret(1) | ||||||
|  |       |       ~~~~~~ | ||||||
|  |    12 |     // avoid cgen whilst warning, later above should error | ||||||
|  |    13 |     main() | ||||||
|  | vlib/v/checker/tests/c_fn_surplus_args.vv:13:2: error: the `main` function cannot be called in the program | ||||||
|  |    11 |     C.ret(1) | ||||||
|  |    12 |     // avoid cgen whilst warning, later above should error | ||||||
|  |    13 |     main() | ||||||
|  |       |     ~~~~~~ | ||||||
|  |    14 | } | ||||||
|  | @ -0,0 +1,14 @@ | ||||||
|  | fn C.no() // untyped
 | ||||||
|  | fn C.y1(int) | ||||||
|  | fn C.ret()byte | ||||||
|  | 
 | ||||||
|  | fn main() { | ||||||
|  | 	C.no(1) // allowed
 | ||||||
|  | 	C.y1() | ||||||
|  | 	C.y1(1) // ok
 | ||||||
|  | 	C.y1(1, 2) | ||||||
|  | 	C.ret() // ok
 | ||||||
|  | 	C.ret(1) | ||||||
|  | 	// avoid cgen whilst warning, later above should error
 | ||||||
|  | 	main() | ||||||
|  | } | ||||||
		Loading…
	
		Reference in New Issue