| 3055 | } |
| 3056 | |
| 3057 | static void add_field(php_class_fields_t *f, CBMArena *arena, const char *name, |
| 3058 | const CBMType *type) { |
| 3059 | if (!f || !name || !type) |
| 3060 | return; |
| 3061 | /* dedup: keep first declaration; constructor inference doesn't override |
| 3062 | * an explicit declaration. */ |
| 3063 | for (int i = 0; i < f->count; i++) { |
| 3064 | if (strcmp(f->field_names[i], name) == 0) |
| 3065 | return; |
| 3066 | } |
| 3067 | if (f->count >= f->cap) { |
| 3068 | int new_cap = f->cap ? f->cap * 2 : 8; |
| 3069 | const char **nn = |
| 3070 | (const char **)cbm_arena_alloc(arena, (size_t)(new_cap + 1) * sizeof(*nn)); |
| 3071 | const CBMType **nt = |
| 3072 | (const CBMType **)cbm_arena_alloc(arena, (size_t)(new_cap + 1) * sizeof(*nt)); |
| 3073 | if (!nn || !nt) |
| 3074 | return; |
| 3075 | for (int i = 0; i < f->count; i++) { |
| 3076 | nn[i] = f->field_names[i]; |
| 3077 | nt[i] = f->field_types[i]; |
| 3078 | } |
| 3079 | f->field_names = nn; |
| 3080 | f->field_types = nt; |
| 3081 | f->cap = new_cap; |
| 3082 | } |
| 3083 | f->field_names[f->count] = cbm_arena_strdup(arena, name); |
| 3084 | f->field_types[f->count] = type; |
| 3085 | f->count++; |
| 3086 | f->field_names[f->count] = NULL; |
| 3087 | f->field_types[f->count] = NULL; |
| 3088 | } |
| 3089 | |
| 3090 | /* Compute the dotted class QN for a given class_declaration node, matching |
| 3091 | * how the unified extractor names defs (module_qn-prefixed). */ |
no test coverage detected