cgen: fix empty struct init using macro (#9787)

pull/9799/head
yuyi 2021-04-18 21:34:25 +08:00 committed by GitHub
parent 8710a0b7b1
commit 75d1b54f7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 24 additions and 11 deletions

View File

@ -5122,9 +5122,10 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
} }
// The rest of the fields are zeroed. // The rest of the fields are zeroed.
// `inited_fields` is a list of fields that have been init'ed, they are skipped // `inited_fields` is a list of fields that have been init'ed, they are skipped
// mut nr_fields := 0 mut nr_fields := 1
if sym.kind == .struct_ { if sym.kind == .struct_ {
info := sym.info as ast.Struct info := sym.info as ast.Struct
nr_fields = info.fields.len
if info.is_union && struct_init.fields.len > 1 { if info.is_union && struct_init.fields.len > 1 {
verror('union must not have more than 1 initializer') verror('union must not have more than 1 initializer')
} }
@ -5205,7 +5206,10 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
} }
g.write(field.name) g.write(field.name)
} else { } else {
g.zero_struct_field(field) if !g.zero_struct_field(field) {
nr_fields--
continue
}
} }
if is_multiline { if is_multiline {
g.writeln(',') g.writeln(',')
@ -5220,7 +5224,11 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
} }
if !initialized { if !initialized {
if nr_fields > 0 {
g.write('0') g.write('0')
} else {
g.write('EMPTY_STRUCT_INITIALIZATION')
}
} }
g.write('}') g.write('}')
@ -5231,19 +5239,26 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) {
} }
} }
fn (mut g Gen) zero_struct_field(field ast.StructField) { fn (mut g Gen) zero_struct_field(field ast.StructField) bool {
sym := g.table.get_type_symbol(field.typ)
if sym.kind == .struct_ {
info := sym.info as ast.Struct
if info.fields.len == 0 {
return false
}
}
field_name := c_name(field.name) field_name := c_name(field.name)
g.write('.$field_name = ') g.write('.$field_name = ')
sym := g.table.get_type_symbol(field.typ)
if field.has_default_expr { if field.has_default_expr {
if sym.kind in [.sum_type, .interface_] { if sym.kind in [.sum_type, .interface_] {
g.expr_with_cast(field.default_expr, field.default_expr_typ, field.typ) g.expr_with_cast(field.default_expr, field.default_expr_typ, field.typ)
return return true
} }
g.expr(field.default_expr) g.expr(field.default_expr)
} else { } else {
g.write(g.type_default(field.typ)) g.write(g.type_default(field.typ))
} }
return true
} }
// fn (mut g Gen) zero_struct_fields(info ast.Struct, inited_fields map[string]int) { // fn (mut g Gen) zero_struct_fields(info ast.Struct, inited_fields map[string]int) {

View File

@ -179,7 +179,7 @@ string _STR_TMP(const char *fmt, ...) {
c_common_macros = ' c_common_macros = '
#define EMPTY_VARG_INITIALIZATION 0 #define EMPTY_VARG_INITIALIZATION 0
#define EMPTY_STRUCT_DECLARATION #define EMPTY_STRUCT_DECLARATION
#define EMPTY_STRUCT_INITIALIZATION 0 #define EMPTY_STRUCT_INITIALIZATION
// Due to a tcc bug, the length of an array needs to be specified, but GCC crashes if it is... // Due to a tcc bug, the length of an array needs to be specified, but GCC crashes if it is...
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[]) #define EMPTY_ARRAY_OF_ELEMS(x,n) (x[])
#define TCCSKIP(x) x #define TCCSKIP(x) x
@ -209,13 +209,13 @@ string _STR_TMP(const char *fmt, ...) {
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#undef __V_GCC__ #undef __V_GCC__
#undef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_INITIALIZATION 0
#endif #endif
#ifdef __TINYC__ #ifdef __TINYC__
#undef EMPTY_STRUCT_DECLARATION #undef EMPTY_STRUCT_DECLARATION
#undef EMPTY_STRUCT_INITIALIZATION
#define EMPTY_STRUCT_DECLARATION char _dummy #define EMPTY_STRUCT_DECLARATION char _dummy
#define EMPTY_STRUCT_INITIALIZATION 0
#undef EMPTY_ARRAY_OF_ELEMS #undef EMPTY_ARRAY_OF_ELEMS
#define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n]) #define EMPTY_ARRAY_OF_ELEMS(x,n) (x[n])
#undef __NOINLINE #undef __NOINLINE

View File

@ -1,9 +1,7 @@
struct NestedGeneric { struct NestedGeneric {
a int
} }
struct Context { struct Context {
b int
} }
struct App { struct App {