From dd9874ab69f4c60abf31e69f81e092633e942ad2 Mon Sep 17 00:00:00 2001 From: "yu.dongliang" <18588496441@163.com> Date: Tue, 23 Jun 2026 15:34:06 +0800 Subject: [PATCH] flat anonymous union & struct. --- core/scf_node.h | 2 + core/scf_variable.h | 1 + examples/flat_anonymous_union.c | 17 ++++++ parse/scf_dfa_class.c | 93 ++++++++++++++++++++++++++++++++- 4 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 examples/flat_anonymous_union.c diff --git a/core/scf_node.h b/core/scf_node.h index 523e324..3a72468 100644 --- a/core/scf_node.h +++ b/core/scf_node.h @@ -38,6 +38,8 @@ struct scf_node_s { uint32_t enum_flag :1; // set when node is a enum type uint32_t class_flag :1; // set when node is a class type uint32_t union_flag :1; // set when node is a union type + uint32_t anon_flag :1; // set when type is anonymous + uint32_t define_flag :1; // set when node is a function & is defined not only declared uint32_t const_flag :1; // set when node is a const type uint32_t split_flag :1; // set when node is a split node of its parent diff --git a/core/scf_variable.h b/core/scf_variable.h index b36a759..9880670 100644 --- a/core/scf_variable.h +++ b/core/scf_variable.h @@ -69,6 +69,7 @@ struct scf_variable_s { uint32_t vla_flag :1; uint32_t arg_flag :1; uint32_t auto_gc_flag:1; + uint32_t anon_flag :1; }; struct scf_index_s diff --git a/examples/flat_anonymous_union.c b/examples/flat_anonymous_union.c new file mode 100644 index 0000000..0988cd5 --- /dev/null +++ b/examples/flat_anonymous_union.c @@ -0,0 +1,17 @@ +int printf(const char* fmt, ...); + +struct A { + int i; + union { + float f; + char c; + }; +}; + +int main() +{ + A a = {128, .f = 3.14}; + + printf("a.i: %d, a.f: %lg\n", a.i, a.f); + return 0; +} diff --git a/parse/scf_dfa_class.c b/parse/scf_dfa_class.c index e81d27e..1052037 100644 --- a/parse/scf_dfa_class.c +++ b/parse/scf_dfa_class.c @@ -46,11 +46,13 @@ static int _class_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) if (!t) { char name[256]; - snprintf(name, sizeof(name) - 1, "anonymous_%d", ast->nb_structs); + snprintf(name, sizeof(name) - 1, "anon_type_%d", ast->nb_structs); t = scf_type_alloc(w, name, SCF_STRUCT + ast->nb_structs, 0); if (!t) return SCF_DFA_ERROR; + + t->node.anon_flag = 1; } if (!t->scope) @@ -97,6 +99,68 @@ static int _class_action_lb(scf_dfa_t* dfa, scf_vector_t* words, void* data) return SCF_DFA_NEXT_WORD; } +static int _class_flat_anon_var(scf_type_t* s) +{ + scf_type_t* t; + scf_variable_t* v; + scf_variable_t* v2; + int i; + int j; + + for (i = 0; i < s->scope->vars->size; ) { + v = s->scope->vars->data[i]; + + if (!v->anon_flag) { + i++; + continue; + } + + t = scf_scope_find_type_type(s->scope, v->type); + assert(t); + + int offset = v->offset; + + assert(0 == scf_vector_del(s->scope->vars, v)); + scf_variable_free(v); + v = NULL; + + if (t->scope->vars->size <= 0) + continue; + + for (j = 0; j < t->scope->vars->size; j++) { + v2 = t->scope->vars->data[j]; + + assert(!v2->anon_flag); + + v2->offset += offset; + } + + int n = s->scope->vars->size; + + int ret = scf_vector_cat(s->scope->vars, t->scope->vars); + if (ret < 0) { + scf_loge("\n"); + return ret; + } + + for (j = n - 1; j >= i; j--) + s->scope->vars->data[j + t->scope->vars->size] = s->scope->vars->data[j]; + + for (j = 0; j < t->scope->vars->size; j++) + s->scope->vars->data[i + j] = t->scope->vars->data[j]; + + scf_loge("i: %d, s->size: %d, t->size: %d\n", i, s->scope->vars->size, t->scope->vars->size); + + n = t->scope->vars->size; + i += n; + + scf_vector_free(t->scope->vars); + t->scope->vars = NULL; + } + + return 0; +} + static int _class_calculate_size(scf_dfa_t* dfa, scf_type_t* s) { scf_variable_t* v; @@ -261,6 +325,7 @@ static int _class_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) scf_stack_t* s = d->module_datas[dfa_module_class.index]; dfa_class_data_t* cd = scf_stack_top(s); scf_lex_word_t* w; + scf_variable_t* v; assert(cd); @@ -271,6 +336,10 @@ static int _class_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) else ret = _union_calculate_size(dfa, cd->current_type); + if (ret < 0) + return SCF_DFA_ERROR; + + ret = _class_flat_anon_var(cd->current_type); if (ret < 0) { scf_loge("\n"); return SCF_DFA_ERROR; @@ -298,6 +367,28 @@ static int _class_action_rb(scf_dfa_t* dfa, scf_vector_t* words, void* data) } dfa->ops->push_word(dfa, w); + + } else if (SCF_LEX_WORD_SEMICOLON == w->type + && s->size > 1 + && cd->current_type->node.anon_flag) { + + char name[256]; + int len = snprintf(name, sizeof(name) - 1, "anon_var_%d", w->line); + + v = scf_variable_alloc(w, cd->current_type); + if (!v) + return -ENOMEM; + + ret = scf_string_copy_cstr_len(v->w->text, name, len); + if (ret < 0) { + scf_variable_free(v); + return ret; + } + + v->anon_flag = 1; + v->member_flag = 1; + + scf_scope_push_var(ast->current_block->scope, v); } return SCF_DFA_NEXT_WORD; -- 2.25.1