From 06825006b3ea89b43c2c5e12179b4abb01b993bb Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 1 Jul 2024 15:00:26 -0300 Subject: [PATCH] cgen: fix array fixed empty struct code generated on clang (fix #21761) (#21764) --- vlib/v/ast/types.v | 10 ++++++++++ vlib/v/gen/c/cgen.v | 12 ++++++++++-- vlib/v/gen/c/dumpexpr.v | 9 +++++++-- vlib/v/tests/array_fixed_empty_struct_test.v | 16 ++++++++++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/array_fixed_empty_struct_test.v diff --git a/vlib/v/ast/types.v b/vlib/v/ast/types.v index 9130e9995faf96..1bb6d8cd354098 100644 --- a/vlib/v/ast/types.v +++ b/vlib/v/ast/types.v @@ -925,6 +925,16 @@ pub fn (t &ArrayFixed) is_compatible(t2 ArrayFixed) bool { return t.size == t2.size && t.elem_type == t2.elem_type } +pub fn (t &TypeSymbol) is_empty_struct_array() bool { + if t.info is ArrayFixed { + elem_sym := global_table.final_sym(t.info.elem_type) + if elem_sym.info is Struct { + return elem_sym.info.fields.len == 0 + } + } + return false +} + pub fn (t &TypeSymbol) is_array_fixed() bool { if t.info is ArrayFixed { return true diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 0948a4f211d3fc..c789dc2dc9bb00 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4295,7 +4295,7 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) { fn (mut g Gen) enum_decl(node ast.EnumDecl) { enum_name := util.no_dots(node.name) is_flag := node.is_flag - if g.pref.ccompiler == 'msvc' { + if g.is_cc_msvc { mut last_value := '0' enum_typ_name := g.table.get_type_name(node.typ) g.enum_typedefs.writeln('') @@ -6278,6 +6278,8 @@ fn (mut g Gen) global_decl(node ast.GlobalDecl) { default_initializer := g.type_default(field.typ) if default_initializer == '{0}' && should_init { def_builder.write_string(' = {0}') + } else if default_initializer == '{EMPTY_STRUCT_INITIALIZATION}' && should_init { + init = '\tmemcpy(${field.name}, (${styp}){${g.type_default(field.typ)}}, sizeof(${styp})); // global' } else { if field.name !in ['as_cast_type_indexes', 'g_memory_block', 'global_allocator'] { init = '\t${field.name} = *(${styp}*)&((${styp}[]){${g.type_default(field.typ)}}[0]); // global' @@ -7161,7 +7163,13 @@ fn (mut g Gen) type_default(typ_ ast.Type) string { .string { return '(string){.str=(byteptr)"", .is_lit=1}' } - .interface_, .sum_type, .array_fixed, .multi_return, .thread { + .array_fixed { + if sym.is_empty_struct_array() { + return '{EMPTY_STRUCT_INITIALIZATION}' + } + return '{0}' + } + .interface_, .sum_type, .multi_return, .thread { return '{0}' } .alias { diff --git a/vlib/v/gen/c/dumpexpr.v b/vlib/v/gen/c/dumpexpr.v index f18af667226d42..8d629c0f87c6b6 100644 --- a/vlib/v/gen/c/dumpexpr.v +++ b/vlib/v/gen/c/dumpexpr.v @@ -227,11 +227,16 @@ fn (mut g Gen) dump_expr_definitions() { surrounder.builder_write_afters(mut dump_fns) if is_fixed_arr_ret { tmp_var := g.new_tmp_var() + init_str := if dump_sym.is_empty_struct_array() { + '{EMPTY_STRUCT_INITIALIZATION}' + } else { + '{0}' + } if typ.is_ptr() { - dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = HEAP(${g.typ(typ.set_nr_muls(0))}, {0});') + dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = HEAP(${g.typ(typ.set_nr_muls(0))}, ${init_str});') dump_fns.writeln('\tmemcpy(${tmp_var}->ret_arr, dump_arg, sizeof(${str_dumparg_type}));') } else { - dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = {0};') + dump_fns.writeln('\t${str_dumparg_ret_type} ${tmp_var} = ${init_str};') dump_fns.writeln('\tmemcpy(${tmp_var}.ret_arr, dump_arg, sizeof(${str_dumparg_type}));') } dump_fns.writeln('\treturn ${tmp_var};') diff --git a/vlib/v/tests/array_fixed_empty_struct_test.v b/vlib/v/tests/array_fixed_empty_struct_test.v new file mode 100644 index 00000000000000..7e33aa26db3319 --- /dev/null +++ b/vlib/v/tests/array_fixed_empty_struct_test.v @@ -0,0 +1,16 @@ +@[has_globals] +module main + +const num_elements = 10 + +struct DummyStruct { +} + +__global ( + d [num_elements]DummyStruct +) + +fn test_main() { + a := dump(d) + assert a.len == num_elements +}