checker: fix pointer checks in translated code
parent
cc227d8520
commit
a55e930c00
|
@ -804,8 +804,12 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
|||
left_name := c.table.type_to_str(left_type)
|
||||
right_name := c.table.type_to_str(right_type)
|
||||
if left_name == right_name {
|
||||
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
|
||||
left_right_pos)
|
||||
if !(node.op == .lt && c.pref.translated) {
|
||||
// Allow `&Foo < &Foo` in translated code.
|
||||
// TODO maybe in unsafe as well?
|
||||
c.error('undefined operation `$left_name` $node.op.str() `$right_name`',
|
||||
left_right_pos)
|
||||
}
|
||||
} else {
|
||||
c.error('mismatched types `$left_name` and `$right_name`', left_right_pos)
|
||||
}
|
||||
|
|
|
@ -801,8 +801,8 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
continue
|
||||
}
|
||||
|
||||
typ := c.check_expr_opt_call(call_arg.expr, c.expr(call_arg.expr))
|
||||
node.args[i].typ = typ
|
||||
arg_typ := c.check_expr_opt_call(call_arg.expr, c.expr(call_arg.expr))
|
||||
node.args[i].typ = arg_typ
|
||||
if c.inside_comptime_for_field {
|
||||
if mut call_arg.expr is ast.Ident {
|
||||
if mut call_arg.expr.obj is ast.Var {
|
||||
|
@ -810,9 +810,9 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
}
|
||||
}
|
||||
typ_sym := c.table.sym(typ)
|
||||
arg_typ_sym := c.table.sym(arg_typ)
|
||||
param_typ_sym := c.table.sym(param.typ)
|
||||
if func.is_variadic && typ.has_flag(.variadic) && node.args.len - 1 > i {
|
||||
if func.is_variadic && arg_typ.has_flag(.variadic) && node.args.len - 1 > i {
|
||||
c.error('when forwarding a variadic variable, it must be the final argument',
|
||||
call_arg.pos)
|
||||
}
|
||||
|
@ -846,7 +846,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
c.error('function `$node.name` parameter `$param.name` is `$tok`, so use `$tok $call_arg.expr` instead',
|
||||
call_arg.expr.pos())
|
||||
} else {
|
||||
c.fail_if_unreadable(call_arg.expr, typ, 'argument')
|
||||
c.fail_if_unreadable(call_arg.expr, arg_typ, 'argument')
|
||||
}
|
||||
}
|
||||
mut final_param_sym := param_typ_sym
|
||||
|
@ -871,22 +871,23 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
}
|
||||
// Handle expected interface
|
||||
if final_param_sym.kind == .interface_ {
|
||||
if c.type_implements(typ, final_param_typ, call_arg.expr.pos()) {
|
||||
if !typ.is_ptr() && !typ.is_pointer() && !c.inside_unsafe
|
||||
&& typ_sym.kind != .interface_ {
|
||||
if c.type_implements(arg_typ, final_param_typ, call_arg.expr.pos()) {
|
||||
if !arg_typ.is_ptr() && !arg_typ.is_pointer() && !c.inside_unsafe
|
||||
&& arg_typ_sym.kind != .interface_ {
|
||||
c.mark_as_referenced(mut &call_arg.expr, true)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
c.check_expected_call_arg(typ, c.unwrap_generic(param.typ), node.language, call_arg) or {
|
||||
c.check_expected_call_arg(arg_typ, c.unwrap_generic(param.typ), node.language,
|
||||
call_arg) or {
|
||||
// str method, allow type with str method if fn arg is string
|
||||
// Passing an int or a string array produces a c error here
|
||||
// Deleting this condition results in propper V error messages
|
||||
// if arg_typ_sym.kind == .string && typ_sym.has_method('str') {
|
||||
// continue
|
||||
// }
|
||||
if typ_sym.kind == .void && param_typ_sym.kind == .string {
|
||||
if arg_typ_sym.kind == .void && param_typ_sym.kind == .string {
|
||||
continue
|
||||
}
|
||||
if param.typ.has_flag(.generic) {
|
||||
|
@ -895,10 +896,10 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if c.pref.translated || c.file.is_translated {
|
||||
// TODO duplicated logic in check_types() (check_types.v)
|
||||
// Allow enums to be used as ints and vice versa in translated code
|
||||
if param.typ == ast.int_type && typ_sym.kind == .enum_ {
|
||||
if param.typ == ast.int_type && arg_typ_sym.kind == .enum_ {
|
||||
continue
|
||||
}
|
||||
if typ == ast.int_type && param_typ_sym.kind == .enum_ {
|
||||
if arg_typ == ast.int_type && param_typ_sym.kind == .enum_ {
|
||||
continue
|
||||
}
|
||||
// In C unsafe number casts are used all the time (e.g. `char*` where
|
||||
|
@ -907,19 +908,19 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if param.typ.is_ptr() {
|
||||
param_is_number = param.typ.deref().is_number()
|
||||
}
|
||||
mut typ_is_number := typ.is_number()
|
||||
if typ.is_ptr() {
|
||||
typ_is_number = typ.deref().is_number()
|
||||
mut typ_is_number := arg_typ.is_number()
|
||||
if arg_typ.is_ptr() {
|
||||
typ_is_number = arg_typ.deref().is_number()
|
||||
}
|
||||
if param_is_number && typ_is_number {
|
||||
continue
|
||||
}
|
||||
// Allow voidptrs for everything
|
||||
if param.typ == ast.voidptr_type_idx || typ == ast.voidptr_type_idx {
|
||||
if param.typ == ast.voidptr_type_idx || arg_typ == ast.voidptr_type_idx {
|
||||
continue
|
||||
}
|
||||
// Allow `[32]i8` as `&i8` etc
|
||||
if (typ_sym.kind == .array_fixed && param_is_number)
|
||||
if (arg_typ_sym.kind == .array_fixed && param_is_number)
|
||||
|| (param_typ_sym.kind == .array_fixed && typ_is_number) {
|
||||
continue
|
||||
}
|
||||
|
@ -927,15 +928,19 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
|
|||
if param.typ.is_any_kind_of_pointer() && typ_is_number {
|
||||
continue
|
||||
}
|
||||
// Allow `&i8` as `int`
|
||||
if arg_typ.is_any_kind_of_pointer() && param_is_number {
|
||||
continue
|
||||
}
|
||||
}
|
||||
c.error('$err.msg() in argument ${i + 1} to `$fn_name`', call_arg.pos)
|
||||
}
|
||||
// Warn about automatic (de)referencing, which will be removed soon.
|
||||
if func.language != .c && !c.inside_unsafe && typ.nr_muls() != param.typ.nr_muls()
|
||||
if func.language != .c && !c.inside_unsafe && arg_typ.nr_muls() != param.typ.nr_muls()
|
||||
&& !(call_arg.is_mut && param.is_mut) && !(!call_arg.is_mut && !param.is_mut)
|
||||
&& param.typ !in [ast.byteptr_type, ast.charptr_type, ast.voidptr_type] {
|
||||
// sym := c.table.sym(typ)
|
||||
c.warn('automatic referencing/dereferencing is deprecated and will be removed soon (got: $typ.nr_muls() references, expected: $param.typ.nr_muls() references)',
|
||||
c.warn('automatic referencing/dereferencing is deprecated and will be removed soon (got: $arg_typ.nr_muls() references, expected: $param.typ.nr_muls() references)',
|
||||
call_arg.pos)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue