flat anonymous union & struct.
authoryu.dongliang <18588496441@163.com>
Tue, 23 Jun 2026 07:34:06 +0000 (15:34 +0800)
committeryu.dongliang <18588496441@163.com>
Tue, 23 Jun 2026 07:34:06 +0000 (15:34 +0800)
core/scf_node.h
core/scf_variable.h
examples/flat_anonymous_union.c [new file with mode: 0644]
parse/scf_dfa_class.c

index 523e324a2b7751042207c84babde32126ff6f8aa..3a724682acf677b4e912f0aa8e1fb3cc4c2bec67 100644 (file)
@@ -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
index b36a75909caac004133e6d8ce46b9716332465c0..98806705e47e4e6e92e1f3d7ebc5cbb1b1713da6 100644 (file)
@@ -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 (file)
index 0000000..0988cd5
--- /dev/null
@@ -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;
+}
index e81d27e05304e0b7d48488911b11ba2fbb913cd4..105203711f17e92e500b1e56ff30403403e9ce3b 100644 (file)
@@ -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;