From 657770e6c176ef9dc24ea25b771ba8c8795c08cf Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 29 Mar 2025 04:01:23 -0300 Subject: [PATCH] cgen: fix `@[keep_args_alive]` with ptr (fix #23973) (#24058) --- vlib/v/gen/c/fn.v | 2 +- vlib/v/tests/c_function/array.c | 136 ++++++++++++++++++++++ vlib/v/tests/c_function/pass_ref_test.c.v | 58 +++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 vlib/v/tests/c_function/array.c create mode 100644 vlib/v/tests/c_function/pass_ref_test.c.v diff --git a/vlib/v/gen/c/fn.v b/vlib/v/gen/c/fn.v index 4ae989106..fed1d2f51 100644 --- a/vlib/v/gen/c/fn.v +++ b/vlib/v/gen/c/fn.v @@ -2577,7 +2577,7 @@ fn (mut g Gen) keep_alive_call_pregen(node ast.CallExpr) int { // evaluation order is preserved expected_type := node.expected_arg_types[i] typ_sym := g.table.sym(expected_type) - typ := typ_sym.cname + typ := g.styp(expected_type) if typ_sym.kind != .array_fixed { g.write('${typ} __tmp_arg_${tmp_cnt_save + i} = ') g.ref_or_deref_arg(arg, expected_type, node.language, false) diff --git a/vlib/v/tests/c_function/array.c b/vlib/v/tests/c_function/array.c new file mode 100644 index 000000000..d8a49fe4b --- /dev/null +++ b/vlib/v/tests/c_function/array.c @@ -0,0 +1,136 @@ +#include +#include +#include +#include + +typedef struct { + char **array_ptr; + int array_len; + int string_len; +} array_t; + +typedef enum flag_bits { + AAA = 0, + BBB = 1, + CCC = 2 +} flag_bits; + +typedef enum flag_bits_main { + AAAA = 0, + BBBB = 1, + CCCC = 2 +} flag_bits_main; + +typedef struct { + array_t arr[4]; + flag_bits enu[2]; +} struct_array; +typedef uint32_t flags; + +typedef union union_t { + float float32[4]; + int32_t int32[4]; + uint32_t uint32[4]; +} union_t; + +array_t* +array_string_new(int array_len, int string_len) +{ + int i; + char **array_ptr = (char**) malloc(array_len * sizeof(char**)); + + for(i = 0; i < array_len; i++) { + array_ptr[i] = (char*) malloc(string_len * sizeof(char)); + } + + array_t *array = (array_t*) malloc(sizeof(array_t)); + array->array_ptr = array_ptr; + array->array_len = array_len; + array->string_len = string_len; + + return array; +} + +int +array_string_set(array_t *array, int index, char *string) +{ + strncpy(array->array_ptr[index], string, array->string_len); + return 0; +} + +char* +array_string_get(array_t *array, int index) +{ + return array->array_ptr[index]; +} + +int +array_string_len(array_t *array) +{ + return array->array_len; +} + +int +array_string_free(array_t *array) +{ + int i; + for(i = 0; i < array->array_len; i++) { + free(array->array_ptr[i]); + } + free(array->array_ptr); + return 0; +} + +char** get_string_array() { + array_t *array = array_string_new(4, 4); + + array_string_set(array, 0, "foo"); + array_string_set(array, 1, "bar"); + array_string_set(array, 2, "bat"); + array_string_set(array, 3, ".... overflowed string"); + + return array->array_ptr; +} + +struct_array get_struct_array() { + int i; + array_t* array = array_string_new(4, 4); + + array_string_set(array, 0, "foo"); + array_string_set(array, 1, "bar"); + array_string_set(array, 2, "bat"); + array_string_set(array, 3, ".... overflowed string"); + + struct_array ret; + for(i = 0; i < array_string_len(array); i++) { + ret.arr[i] = *array; + }; + free(array); + + return ret; +} + +flags get_enum() { + flag_bits ret = AAA; + return ret; +} + +union_t get_union() { + uint32_t r = 123; + union_t ret; + ret.uint32[0] = r; + ret.uint32[1] = r; + ret.uint32[2] = r; + ret.uint32[3] = r; + return ret; +} + +void get_stub(flag_bits param[2]) {} + +void get_stub_main(flag_bits_main param[2]) {} + +void +set_struct_array(struct_array* param) +{ + puts("\nset struct_array\n"); +} \ No newline at end of file diff --git a/vlib/v/tests/c_function/pass_ref_test.c.v b/vlib/v/tests/c_function/pass_ref_test.c.v new file mode 100644 index 000000000..31987095e --- /dev/null +++ b/vlib/v/tests/c_function/pass_ref_test.c.v @@ -0,0 +1,58 @@ +module main + +#include "@VMODROOT/array.c" + +enum Flag_bits { + aaa = 0 + bbb = 1 + ccc = 2 +} + +pub type Array_t = C.array_t + +@[typedef] +struct C.array_t { +pub mut: + array_ptr &&char + array_len int + string_len int +} + +pub type Struct_array = C.struct_array + +@[typedef] +struct C.struct_array { +pub mut: + arr [4]Array_t + enu [2]Flag_bits +} + +fn C.get_string_array() &&char +@[inline] +pub fn get_string_array() &&char { + return C.get_string_array() +} + +fn C.get_struct_array() Struct_array +@[inline] +pub fn get_struct_array() Struct_array { + return C.get_struct_array() +} + +fn C.array_string_free(&Array_t) + +@[keep_args_alive] +fn C.set_struct_array(&Struct_array) +@[inline] +pub fn set_struct_array(param &Struct_array) { + C.set_struct_array(param) +} + +fn test_main() { + struct_array := get_struct_array() + + set_struct_array(&Struct_array{}) + set_struct_array(&struct_array) + + C.array_string_free(&struct_array.arr[0]) +} -- 2.39.5