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