1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker/gen/parser: varg with pointer type fix: #15943 (#15944)

This commit is contained in:
Joe C 2022-10-06 15:58:07 +11:00 committed by GitHub
parent f0871b87a4
commit 18f0040388
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 45 additions and 23 deletions

View File

@ -236,10 +236,6 @@ fn (mut c Checker) fn_decl(mut node ast.FnDecl) {
}
}
}
if (c.pref.translated || c.file.is_translated) && node.is_variadic && param.typ.is_ptr() {
// TODO c2v hack to fix `(const char *s, ...)`
param.typ = ast.int_type.ref()
}
}
}
if node.language == .v && node.name.after_char(`.`) == 'init' && !node.is_method
@ -1051,25 +1047,32 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
}
if c.pref.translated || c.file.is_translated {
// in case of variadic make sure to use array elem type for checks
// check_expected_call_arg already does this before checks also.
param_type := if param.typ.has_flag(.variadic) {
c.table.sym(param.typ).array_info().elem_type
} else {
param.typ
}
// 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 && arg_typ_sym.kind == .enum_ {
if param_type.idx() in ast.integer_type_idxs && arg_typ_sym.kind == .enum_ {
continue
}
if arg_typ == ast.int_type && param_typ_sym.kind == .enum_ {
if arg_typ.idx() in ast.integer_type_idxs && param_typ_sym.kind == .enum_ {
continue
}
if (arg_typ == ast.bool_type && param.typ.is_int())
|| (arg_typ.is_int() && param.typ == ast.bool_type) {
if (arg_typ == ast.bool_type && param_type.is_int())
|| (arg_typ.is_int() && param_type == ast.bool_type) {
continue
}
// In C unsafe number casts are used all the time (e.g. `char*` where
// `int*` is expected etc), so just allow them all.
mut param_is_number := c.table.unaliased_type(param.typ).is_number()
if param.typ.is_ptr() {
param_is_number = param.typ.deref().is_number()
mut param_is_number := c.table.unaliased_type(param_type).is_number()
if param_type.is_ptr() {
param_is_number = param_type.deref().is_number()
}
mut typ_is_number := c.table.unaliased_type(arg_typ).is_number()
if arg_typ.is_ptr() {
@ -1079,18 +1082,18 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
continue
}
// Allow voidptrs for everything
if param.typ == ast.voidptr_type_idx || arg_typ == ast.voidptr_type_idx {
if param_type == ast.voidptr_type_idx || arg_typ == ast.voidptr_type_idx {
continue
}
if param.typ.is_any_kind_of_pointer() && arg_typ.is_any_kind_of_pointer() {
if param_type.is_any_kind_of_pointer() && arg_typ.is_any_kind_of_pointer() {
continue
}
param_typ_sym_ := c.table.sym(c.table.unaliased_type(param.typ))
param_typ_sym_ := c.table.sym(c.table.unaliased_type(param_type))
arg_typ_sym_ := c.table.sym(c.table.unaliased_type(arg_typ))
// Allow `[32]i8` as `&i8` etc
if ((arg_typ_sym_.kind == .array_fixed || arg_typ_sym_.kind == .array)
&& (param_is_number
|| c.table.unaliased_type(param.typ).is_any_kind_of_pointer()))
|| c.table.unaliased_type(param_type).is_any_kind_of_pointer()))
|| ((param_typ_sym_.kind == .array_fixed || param_typ_sym_.kind == .array)
&& (typ_is_number || c.table.unaliased_type(arg_typ).is_any_kind_of_pointer())) {
continue
@ -1107,7 +1110,7 @@ pub fn (mut c Checker) fn_call(mut node ast.CallExpr, mut continue_check &bool)
}
}
// Allow `int` as `&i8`
if param.typ.is_any_kind_of_pointer() && typ_is_number {
if param_type.is_any_kind_of_pointer() && typ_is_number {
continue
}
// Allow `&i8` as `int`

View File

@ -941,11 +941,9 @@ fn (mut g Gen) base_type(_t ast.Type) string {
if t.has_flag(.shared_f) {
styp = g.find_or_register_shared(t, styp)
}
if !t.has_flag(.variadic) {
nr_muls := g.unwrap_generic(t).nr_muls()
if nr_muls > 0 {
styp += strings.repeat(`*`, nr_muls)
}
nr_muls := g.unwrap_generic(t).nr_muls()
if nr_muls > 0 {
styp += strings.repeat(`*`, nr_muls)
}
return styp
}

View File

@ -559,7 +559,10 @@ fn (mut g Gen) fn_decl_params(params []ast.Param, scope &ast.Scope, is_variadic
} else {
c_name(param.name)
}
typ := g.unwrap_generic(param.typ)
mut typ := g.unwrap_generic(param.typ)
if g.pref.translated && g.file.is_translated && param.typ.has_flag(.variadic) {
typ = g.table.sym(g.unwrap_generic(param.typ)).array_info().elem_type.set_flag(.variadic)
}
param_type_sym := g.table.sym(typ)
mut param_type_name := g.typ(typ) // util.no_dots(param_type_sym.name)
if param_type_sym.kind == .function {

View File

@ -967,7 +967,8 @@ fn (mut p Parser) fn_args() ([]ast.Param, bool, bool) {
}
}
if is_variadic {
typ = ast.new_type(p.table.find_or_register_array(typ)).derive(typ).set_flag(.variadic)
// derive flags, however nr_muls only needs to be set on the array elem type, so clear it on the arg type
typ = ast.new_type(p.table.find_or_register_array(typ)).derive(typ).set_nr_muls(0).set_flag(.variadic)
}
for i, arg_name in arg_names {
alanguage := p.table.sym(typ).language

View File

@ -97,3 +97,20 @@ fn test_fn_variadic_method_no_args() {
a := VaTestStruct{}
a.variadic_method_no_args('marko')
}
// test vargs with pointer type
fn take_variadic_string_ptr(strings ...&string) {
take_array_string_ptr(strings)
}
fn take_array_string_ptr(strings []&string) {
assert strings.len == 2
assert *strings[0] == 'a'
assert *strings[1] == 'b'
}
fn test_varg_pointer() {
a := 'a'
b := 'b'
take_variadic_string_ptr(&a, &b)
}