kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

parse_type.c (55197B)


      1 /* parse_type.c — decl-specs, struct/union/enum, declarators,
      2  * __attribute__ parsing. */
      3 
      4 #include "parse/parse_priv.h"
      5 
      6 /* ============================================================
      7  * Type helpers
      8  * ============================================================ */
      9 
     10 static const Type* ty_int(Parser* p) { return type_prim(p->pool, TY_INT); }
     11 static const Type* ty_size_t(Parser* p) {
     12   return c_abi_size_type(p->abi, p->pool);
     13 }
     14 
     15 /* __int128 is a 16-byte scalar that the ABI, runtime ti3 helpers, and the
     16  * HAS_INT128 capability only support on 64-bit targets (matching GCC/Clang,
     17  * which reject __int128 on 32-bit architectures). Gate on the target pointer
     18  * width: ptr_size == 8 means 64-bit (rv64/x64/aa64) and int128 is available;
     19  * a 32-bit target (rv32, with a 4-byte pointer) has no working int128. */
     20 static int target_has_int128(Parser* p) {
     21   return kit_compiler_target_spec(p->c).ptr_size == 8;
     22 }
     23 
     24 /* ============================================================
     25  * GNU __attribute__ (Phase 1 — parse + carry; no semantic wire-up)
     26  * ============================================================ */
     27 
     28 static const struct {
     29   const char* name;
     30   AttrKind kind;
     31   AttrArgShape shape;
     32 } kAttrTable[] = {
     33     {"packed", ATTR_PACKED, AS_NONE},
     34     {"aligned", ATTR_ALIGNED, AS_INT_OPT},
     35     {"section", ATTR_SECTION, AS_STRING},
     36     {"used", ATTR_USED, AS_NONE},
     37     {"noreturn", ATTR_NORETURN, AS_NONE},
     38     {"alias", ATTR_ALIAS, AS_STRING},
     39     {"weak", ATTR_WEAK, AS_NONE},
     40     {"visibility", ATTR_VISIBILITY, AS_STRING},
     41     {"always_inline", ATTR_ALWAYS_INLINE, AS_NONE},
     42     {"noinline", ATTR_NOINLINE, AS_NONE},
     43     {"unused", ATTR_UNUSED, AS_NONE},
     44     {"deprecated", ATTR_DEPRECATED, AS_OPAQUE},
     45     {"warn_unused_result", ATTR_WARN_UNUSED_RESULT, AS_NONE},
     46     {"format", ATTR_FORMAT, AS_FORMAT},
     47     {"nonnull", ATTR_NONNULL, AS_OPAQUE},
     48     {"returns_nonnull", ATTR_RETURNS_NONNULL, AS_NONE},
     49     {"pure", ATTR_PURE, AS_NONE},
     50     {"const", ATTR_CONST, AS_NONE},
     51     {"malloc", ATTR_MALLOC, AS_OPAQUE},
     52     {"nothrow", ATTR_NOTHROW, AS_NONE},
     53     {"leaf", ATTR_LEAF, AS_NONE},
     54     {"cold", ATTR_COLD, AS_NONE},
     55     {"hot", ATTR_HOT, AS_NONE},
     56     {"constructor", ATTR_CONSTRUCTOR, AS_INT_OPT},
     57     {"destructor", ATTR_DESTRUCTOR, AS_INT_OPT},
     58     {"cleanup", ATTR_CLEANUP, AS_IDENT},
     59     {"mode", ATTR_MODE, AS_IDENT},
     60     {"vector_size", ATTR_VECTOR_SIZE, AS_INT},
     61     {"transparent_union", ATTR_TRANSPARENT_UNION, AS_NONE},
     62     {"gnu_inline", ATTR_GNU_INLINE, AS_NONE},
     63     {"fallthrough", ATTR_FALLTHROUGH, AS_NONE},
     64     {"sentinel", ATTR_SENTINEL, AS_OPAQUE},
     65     {"no_instrument_function", ATTR_NO_INSTRUMENT_FUNCTION, AS_NONE},
     66     {"no_sanitize", ATTR_NO_SANITIZE, AS_OPAQUE},
     67     {"import_module", ATTR_IMPORT_MODULE, AS_STRING},
     68     {"import_name", ATTR_IMPORT_NAME, AS_STRING},
     69 };
     70 
     71 static SrcLoc tok_loc(const Tok* t) { return t->loc; }
     72 
     73 static void attr_canon_range(const char* s, size_t len, const char** out_p,
     74                              size_t* out_len);
     75 
     76 static int accept_kw(Parser* p, CKw k) {
     77   if (is_kw(p, &p->cur, k)) {
     78     advance(p);
     79     return 1;
     80   }
     81   return 0;
     82 }
     83 
     84 static int attr_sym_canon_eq(Parser* p, Sym sym, const char* want) {
     85   KitSlice sym_sl = kit_sym_str(p->pool->c, sym);
     86   size_t len = sym_sl.len;
     87   const char* s = sym_sl.s;
     88   const char* cs;
     89   size_t clen;
     90   if (!s) return 0;
     91   attr_canon_range(s, len, &cs, &clen);
     92   return kit_slice_eq_cstr((KitSlice){.s = cs, .len = clen}, want);
     93 }
     94 
     95 static const Type* attrs_apply_type_mode(Parser* p, const Type* base,
     96                                          const Attr* attrs) {
     97   for (const Attr* a = attrs; a; a = a->next) {
     98     if (a->kind != ATTR_MODE || a->nargs == 0) continue;
     99     if (attr_sym_canon_eq(p, a->v.sym, "TI")) {
    100       const Type* u = type_unqual(p->pool, base);
    101       int is_unsigned =
    102           u && type_is_int(u) && c_abi_type_info(p->abi, u).signed_ == 0;
    103       if (!target_has_int128(p)) {
    104         perr(p, "__int128 is not supported on the target architecture");
    105       }
    106       return type_prim(p->pool, is_unsigned ? TY_UINT128 : TY_INT128);
    107     }
    108   }
    109   return base;
    110 }
    111 
    112 static CKw ident_kw(const Parser* p, Sym name) {
    113   return ident_kw_inline(p, name);
    114 }
    115 
    116 int starts_attr(const Parser* p) {
    117   return p->cur.kind == TOK_IDENT && p->cur.v.ident == p->sym_attribute;
    118 }
    119 
    120 static int starts_asm_label(const Parser* p) {
    121   return is_kw(p, &p->cur, KW_ASM) || is_kw(p, &p->cur, KW_BUILTIN_ASM);
    122 }
    123 
    124 static Sym parse_asm_label(Parser* p) {
    125   Sym label = 0;
    126   advance(p); /* asm / __asm / __asm__ */
    127   expect_punct(p, '(', "'(' after asm label");
    128   if (p->cur.kind != TOK_STR) {
    129     perr(p, "expected string literal in asm label");
    130   }
    131   /* Capture the label string for the declarator currently being parsed. For a
    132    * `register T x __asm__("r10")` local this is the hard register name the
    133    * variable binds to. Other asm labels (symbol renames) are still effectively
    134    * ignored by callers that do not consume DeclaratorInfo.asm_label. */
    135   {
    136     Tok t = p->cur;
    137     size_t nlen = 0;
    138     u8* bytes = decode_string_literal(p, &t, &nlen);
    139     u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
    140     label = kit_sym_intern(p->pool->c,
    141                            (KitSlice){.s = (const char*)bytes, .len = ilen});
    142     kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
    143                                            bytes, 0);
    144   }
    145   do {
    146     advance(p);
    147   } while (p->cur.kind == TOK_STR);
    148   expect_punct(p, ')', "')' after asm label");
    149   return label;
    150 }
    151 
    152 static void parse_attrs_and_asm_into(Parser* p, Attr** attrs_out,
    153                                      Attr** local_attrs, Sym* asm_label_out) {
    154   for (;;) {
    155     if (starts_attr(p)) {
    156       if (attrs_out)
    157         parse_attrs_into(p, attrs_out);
    158       else
    159         parse_attrs_into(p, local_attrs);
    160       continue;
    161     }
    162     if (starts_asm_label(p)) {
    163       Sym label = parse_asm_label(p);
    164       if (asm_label_out) *asm_label_out = label;
    165       continue;
    166     }
    167     break;
    168   }
    169 }
    170 
    171 static void parse_and_discard_attrs_or_asm(Parser* p) {
    172   for (;;) {
    173     if (starts_attr(p)) {
    174       parse_and_discard_attributes(p);
    175       continue;
    176     }
    177     if (starts_asm_label(p)) {
    178       (void)parse_asm_label(p);
    179       continue;
    180     }
    181     break;
    182   }
    183 }
    184 
    185 static void attr_canon_range(const char* s, size_t len, const char** out_p,
    186                              size_t* out_len) {
    187   if (len >= 4 && s[0] == '_' && s[1] == '_' && s[len - 1] == '_' &&
    188       s[len - 2] == '_') {
    189     *out_p = s + 2;
    190     *out_len = len - 4;
    191     return;
    192   }
    193   *out_p = s;
    194   *out_len = len;
    195 }
    196 
    197 static AttrKind classify_attr(Parser* p, Sym name, AttrArgShape* shape_out) {
    198   KitSlice name_sl = kit_sym_str(p->pool->c, name);
    199   size_t len = name_sl.len;
    200   const char* s = name_sl.s;
    201   const char* cs;
    202   size_t clen;
    203   size_t i;
    204   if (!s) {
    205     *shape_out = AS_OPAQUE;
    206     return ATTR_UNKNOWN;
    207   }
    208   attr_canon_range(s, len, &cs, &clen);
    209   for (i = 0; i < sizeof(kAttrTable) / sizeof(kAttrTable[0]); ++i) {
    210     const char* tn = kAttrTable[i].name;
    211     if (kit_slice_eq_cstr((KitSlice){.s = cs, .len = clen}, tn)) {
    212       *shape_out = kAttrTable[i].shape;
    213       return kAttrTable[i].kind;
    214     }
    215   }
    216   *shape_out = AS_OPAQUE;
    217   return ATTR_UNKNOWN;
    218 }
    219 
    220 static void skip_balanced_parens(Parser* p) {
    221   int depth;
    222   if (!is_punct(&p->cur, '(')) perr(p, "internal: skip_balanced_parens");
    223   depth = 1;
    224   advance(p);
    225   while (depth > 0) {
    226     if (p->cur.kind == TOK_EOF) {
    227       perr(p, "unexpected EOF inside attribute arguments");
    228     }
    229     if (is_punct(&p->cur, '('))
    230       ++depth;
    231     else if (is_punct(&p->cur, ')')) {
    232       --depth;
    233       if (depth == 0) {
    234         advance(p);
    235         return;
    236       }
    237     }
    238     advance(p);
    239   }
    240 }
    241 
    242 static void parse_attr_args(Parser* p, Attr* a, AttrArgShape shape,
    243                             const char* attr_diag_name) {
    244   if (!is_punct(&p->cur, '(')) {
    245     if (shape == AS_NONE || shape == AS_OPTIONAL || shape == AS_INT_OPT ||
    246         shape == AS_OPAQUE) {
    247       return;
    248     }
    249     perr(p, "attribute '%.*s' expects '(' arguments",
    250          KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
    251   }
    252   switch (shape) {
    253     case AS_NONE: {
    254       advance(p); /* '(' */
    255       if (!accept_punct(p, ')')) {
    256         perr(p, "attribute '%.*s' takes no arguments",
    257              KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
    258       }
    259       return;
    260     }
    261     case AS_OPTIONAL: {
    262       skip_balanced_parens(p);
    263       return;
    264     }
    265     case AS_INT:
    266     case AS_INT_OPT: {
    267       SrcLoc loc;
    268       advance(p); /* '(' */
    269       if (is_punct(&p->cur, ')')) {
    270         if (shape == AS_INT) {
    271           perr(p, "attribute '%.*s' expects an integer argument",
    272                KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
    273         }
    274         advance(p);
    275         return;
    276       }
    277       loc = tok_loc(&p->cur);
    278       a->v.i = eval_const_int(p, loc);
    279       if (a->kind == ATTR_ALIGNED && a->v.i > 0 &&
    280           (((u64)a->v.i & ((u64)a->v.i - 1u)) != 0)) {
    281         perr(p, "attribute 'aligned' argument must be a power of two");
    282       }
    283       a->nargs = 1;
    284       expect_punct(p, ')', "')' after attribute integer argument");
    285       return;
    286     }
    287     case AS_STRING: {
    288       advance(p); /* '(' */
    289       if (p->cur.kind != TOK_STR) {
    290         perr(p, "attribute '%.*s' expects a string literal",
    291              KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
    292       }
    293       {
    294         Tok t = p->cur;
    295         size_t nlen = 0;
    296         u8* bytes = decode_string_literal(p, &t, &nlen);
    297         u32 ilen = (nlen > 0) ? (u32)(nlen - 1) : 0;
    298         a->v.sym = kit_sym_intern(
    299             p->pool->c, (KitSlice){.s = (const char*)bytes, .len = ilen});
    300         kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
    301                                                bytes, 0);
    302       }
    303       a->nargs = 1;
    304       advance(p);
    305       expect_punct(p, ')', "')' after attribute string argument");
    306       return;
    307     }
    308     case AS_IDENT: {
    309       advance(p); /* '(' */
    310       if (p->cur.kind != TOK_IDENT) {
    311         perr(p, "attribute '%.*s' expects an identifier",
    312              KIT_SLICE_ARG(kit_slice_cstr(attr_diag_name)));
    313       }
    314       a->v.sym = p->cur.v.ident;
    315       a->nargs = 1;
    316       advance(p);
    317       expect_punct(p, ')', "')' after attribute identifier argument");
    318       return;
    319     }
    320     case AS_FORMAT: {
    321       SrcLoc mloc, nloc;
    322       i64 mv, nv;
    323       advance(p); /* '(' */
    324       if (p->cur.kind != TOK_IDENT) {
    325         perr(p, "attribute 'format' expects (archetype, m, n)");
    326       }
    327       advance(p);
    328       expect_punct(p, ',', "',' after format archetype");
    329       mloc = tok_loc(&p->cur);
    330       mv = eval_const_int(p, mloc);
    331       expect_punct(p, ',', "',' after format string-index");
    332       nloc = tok_loc(&p->cur);
    333       nv = eval_const_int(p, nloc);
    334       if (mv < 0 || mv > 0xFFFF || nv < 0 || nv > 0xFFFF) {
    335         perr(p, "attribute 'format' indices out of range");
    336       }
    337       a->v.format.fmt_idx = (u16)mv;
    338       a->v.format.first = (u16)nv;
    339       a->nargs = 3;
    340       expect_punct(p, ')', "')' after format arguments");
    341       return;
    342     }
    343     case AS_OPAQUE:
    344     default: {
    345       skip_balanced_parens(p);
    346       return;
    347     }
    348   }
    349 }
    350 
    351 Attr* parse_attribute_spec_list(Parser* p) {
    352   Attr* head = NULL;
    353   Attr* tail = NULL;
    354   while (starts_attr(p)) {
    355     SrcLoc kw_loc = tok_loc(&p->cur);
    356     advance(p); /* __attribute__ */
    357     expect_punct(p, '(', "'(' after __attribute__");
    358     expect_punct(p, '(', "'((' after __attribute__");
    359     for (;;) {
    360       Sym aname;
    361       AttrArgShape shape;
    362       Attr* a;
    363       const char* diag_name;
    364       size_t diag_len;
    365       const char* canon;
    366       size_t canon_len;
    367       while (accept_punct(p, ',')) { /* skip */
    368       }
    369       if (is_punct(&p->cur, ')')) break;
    370       if (p->cur.kind != TOK_IDENT) {
    371         perr(p, "expected attribute name");
    372       }
    373       aname = p->cur.v.ident;
    374       a = arena_new(p->pool->arena, Attr);
    375       if (!a) perr(p, "out of memory in parse_attribute_spec_list");
    376       memset(a, 0, sizeof *a);
    377       a->loc = tok_loc(&p->cur);
    378       a->name = aname;
    379       a->kind = (u16)classify_attr(p, aname, &shape);
    380       advance(p);
    381       {
    382         KitSlice aname_sl = kit_sym_str(p->pool->c, aname);
    383         diag_name = aname_sl.s;
    384         diag_len = aname_sl.len;
    385       }
    386       attr_canon_range(diag_name, diag_len, &canon, &canon_len);
    387       (void)canon;
    388       (void)canon_len;
    389       parse_attr_args(p, a, shape, diag_name ? diag_name : "<unknown>");
    390       if (tail)
    391         tail->next = a;
    392       else
    393         head = a;
    394       tail = a;
    395       if (!accept_punct(p, ',')) break;
    396     }
    397     expect_punct(p, ')', "')' after attribute list");
    398     expect_punct(p, ')', "'))' after attribute list");
    399     (void)kw_loc;
    400   }
    401   return head;
    402 }
    403 
    404 void parse_and_discard_attributes(Parser* p) {
    405   (void)parse_attribute_spec_list(p);
    406 }
    407 
    408 /* Append `add` to the end of `*head` (linked via Attr.next). */
    409 void attr_list_append(Attr** head, Attr* add) {
    410   if (!add) return;
    411   if (!*head) {
    412     *head = add;
    413     return;
    414   }
    415   Attr* tail = *head;
    416   while (tail->next) tail = tail->next;
    417   tail->next = add;
    418 }
    419 
    420 /* If `starts_attr`, parse and append to `*sink`. No-op otherwise. */
    421 void parse_attrs_into(Parser* p, Attr** sink) {
    422   if (starts_attr(p)) attr_list_append(sink, parse_attribute_spec_list(p));
    423 }
    424 
    425 #define PARSE_ATTR_ALIGNED_DEFAULT 16u
    426 
    427 static void attrs_to_record_opts(const Attr* a, TypeRecordOpts* opts) {
    428   for (; a; a = a->next) {
    429     if (a->kind == ATTR_PACKED) {
    430       opts->packed = 1;
    431     } else if (a->kind == ATTR_ALIGNED) {
    432       u32 v = (a->nargs == 0) ? PARSE_ATTR_ALIGNED_DEFAULT : (u32)a->v.i;
    433       if (v > opts->align_override) opts->align_override = (u16)v;
    434     }
    435   }
    436 }
    437 
    438 static void attrs_to_field(const Attr* a, Field* f) {
    439   for (; a; a = a->next) {
    440     if (a->kind == ATTR_PACKED) {
    441       f->packed = 1;
    442     } else if (a->kind == ATTR_ALIGNED) {
    443       u32 v = (a->nargs == 0) ? PARSE_ATTR_ALIGNED_DEFAULT : (u32)a->v.i;
    444       if (v > f->align_override) f->align_override = (u16)v;
    445     }
    446   }
    447 }
    448 
    449 u32 attrs_pick_aligned(const Attr* a) {
    450   u32 best = 0;
    451   for (; a; a = a->next) {
    452     if (a->kind == ATTR_ALIGNED) {
    453       u32 v = (a->nargs == 0) ? PARSE_ATTR_ALIGNED_DEFAULT : (u32)a->v.i;
    454       if (v > best) best = v;
    455     }
    456   }
    457   return best;
    458 }
    459 
    460 static int is_power_of_two_u32(u32 v) { return v != 0 && (v & (v - 1u)) == 0; }
    461 
    462 static void validate_atomic_operand(Parser* p, const Type* ty) {
    463   if (!ty) perr(p, "_Atomic requires an object type");
    464   if (ty->qual) perr(p, "_Atomic operand must not be qualified");
    465   if (ty->kind == TY_ARRAY || ty->kind == TY_FUNC || ty->kind == TY_VOID) {
    466     perr(p, "_Atomic operand must be an object type");
    467   }
    468 }
    469 
    470 void validate_decl_type_constraints(Parser* p, const DeclSpecs* specs,
    471                                     const Type* ty, int is_function,
    472                                     int is_member) {
    473   const Type* u = ty ? type_unqual(p->pool, ty) : NULL;
    474   if (!u) return;
    475   if (specs->quals & Q_RESTRICT) {
    476     perr(p, "restrict requires pointer type");
    477   }
    478   if ((ty->qual & Q_RESTRICT) && ty->kind != TY_PTR) {
    479     perr(p, "restrict requires pointer type");
    480   }
    481   if (is_member) {
    482     if (specs->storage != DS_AUTO || specs->storage_explicit) {
    483       perr(p, "storage-class specifier is invalid for struct member");
    484     }
    485     if (specs->flags & DF_INLINE)
    486       perr(p, "inline is invalid for struct member");
    487     if (specs->flags & DF_NORETURN)
    488       perr(p, "_Noreturn is invalid for struct member");
    489     if (specs->flags & DF_THREAD)
    490       perr(p, "_Thread_local is invalid for struct member");
    491   }
    492   if (u->kind == TY_VOID && !is_function && specs->storage != DS_TYPEDEF) {
    493     perr(p, "object may not have void type");
    494   }
    495   if ((specs->flags & DF_INLINE) && !is_function) {
    496     perr(p, "inline may only appear on a function declaration");
    497   }
    498   if ((specs->flags & DF_NORETURN) && !is_function) {
    499     perr(p, "_Noreturn may only appear on a function declaration");
    500   }
    501   if ((specs->flags & DF_THREAD) &&
    502       (is_function || specs->storage == DS_TYPEDEF)) {
    503     perr(p, "_Thread_local may only appear on object declarations");
    504   }
    505   if (specs->align) {
    506     u32 natural = 0;
    507     if (!is_power_of_two_u32(specs->align)) {
    508       perr(p, "_Alignas requires a power-of-two alignment");
    509     }
    510     if (is_function || specs->storage == DS_TYPEDEF) {
    511       perr(p, "_Alignas is invalid on this declaration");
    512     }
    513     if (u->kind == TY_VOID || u->kind == TY_FUNC) {
    514       perr(p, "_Alignas requires an object type");
    515     }
    516     natural = c_abi_alignof(p->abi, ty);
    517     if (specs->align < natural) {
    518       perr(p, "_Alignas cannot weaken natural alignment");
    519     }
    520   }
    521 }
    522 
    523 /* ============================================================
    524  * resolve_type_specs
    525  * ============================================================ */
    526 
    527 const Type* resolve_type_specs(Parser* p, const TypeSpecAccum* a, SrcLoc loc) {
    528   if (!a->saw_explicit_type) return NULL;
    529   if (a->long_count > 2) {
    530     compiler_panic(p->c, loc, "too many long type specifiers");
    531   }
    532   if (a->saw_void) {
    533     if (a->saw_char || a->saw_int || a->saw_short || a->long_count ||
    534         a->saw_signed || a->saw_unsigned || a->saw_bool || a->saw_float ||
    535         a->saw_double) {
    536       compiler_panic(p->c, loc, "conflicting type specifiers (void mixed)");
    537     }
    538     return type_void(p->pool);
    539   }
    540   if (a->saw_bool) {
    541     if (a->saw_char || a->saw_int || a->saw_short || a->long_count ||
    542         a->saw_signed || a->saw_unsigned || a->saw_float || a->saw_double) {
    543       compiler_panic(p->c, loc, "conflicting type specifiers (_Bool mixed)");
    544     }
    545     return type_prim(p->pool, TY_BOOL);
    546   }
    547   if (a->saw_char) {
    548     if (a->saw_int || a->saw_short || a->long_count || a->saw_float ||
    549         a->saw_double) {
    550       compiler_panic(p->c, loc, "conflicting type specifiers (char mixed)");
    551     }
    552     if (a->saw_unsigned) return type_prim(p->pool, TY_UCHAR);
    553     if (a->saw_signed) return type_prim(p->pool, TY_SCHAR);
    554     return type_prim(p->pool, TY_CHAR);
    555   }
    556   if (a->saw_float) {
    557     if (a->saw_int || a->saw_short || a->long_count || a->saw_signed ||
    558         a->saw_unsigned || a->saw_double) {
    559       compiler_panic(p->c, loc, "conflicting type specifiers (float mixed)");
    560     }
    561     return type_prim(p->pool, TY_FLOAT);
    562   }
    563   if (a->saw_double) {
    564     if (a->saw_int || a->saw_short || a->saw_signed || a->saw_unsigned ||
    565         a->long_count > 1) {
    566       compiler_panic(p->c, loc, "conflicting type specifiers (double mixed)");
    567     }
    568     return type_prim(p->pool, a->long_count ? TY_LDOUBLE : TY_DOUBLE);
    569   }
    570   if (a->saw_short) {
    571     if (a->long_count) {
    572       compiler_panic(p->c, loc, "conflicting type specifiers (short long)");
    573     }
    574     return type_prim(p->pool, a->saw_unsigned ? TY_USHORT : TY_SHORT);
    575   }
    576   if (a->saw_int128) {
    577     if (!target_has_int128(p)) {
    578       perr(p, "__int128 is not supported on the target architecture");
    579     }
    580     return type_prim(p->pool, a->saw_unsigned ? TY_UINT128 : TY_INT128);
    581   }
    582   if (a->long_count == 2) {
    583     return type_prim(p->pool, a->saw_unsigned ? TY_ULLONG : TY_LLONG);
    584   }
    585   if (a->long_count == 1) {
    586     return type_prim(p->pool, a->saw_unsigned ? TY_ULONG : TY_LONG);
    587   }
    588   if (a->saw_unsigned) return type_prim(p->pool, TY_UINT);
    589   if (a->saw_signed || a->saw_int) return type_prim(p->pool, TY_INT);
    590   return type_prim(p->pool, TY_INT);
    591 }
    592 
    593 /* ============================================================
    594  * parse_decl_specs
    595  * ============================================================ */
    596 
    597 int parse_decl_specs(Parser* p, DeclSpecs* out) {
    598   TypeSpecAccum acc;
    599   SrcLoc loc;
    600   int seen = 0;
    601   int storage_seen = 0;
    602   const Type* tagged_ty = NULL;
    603   memset(&acc, 0, sizeof acc);
    604   out->type = NULL;
    605   out->storage = DS_AUTO;
    606   out->flags = DF_NONE;
    607   out->quals = 0;
    608   out->storage_explicit = 0;
    609   out->pad = 0;
    610   out->align = 0;
    611   out->vla_byte_slot = FRAME_SLOT_NONE;
    612   out->vla_bounds = NULL;
    613   out->attrs = NULL;
    614   loc = tok_loc(&p->cur);
    615   for (;;) {
    616     Tok t = p->cur;
    617     if (starts_attr(p)) {
    618       Attr* a = parse_attribute_spec_list(p);
    619       if (a) {
    620         Attr* tail = a;
    621         while (tail->next) tail = tail->next;
    622         tail->next = out->attrs;
    623         out->attrs = a;
    624       }
    625       seen = 1;
    626       continue;
    627     }
    628     if (is_kw(p, &t, KW_STRUCT) || is_kw(p, &t, KW_UNION)) {
    629       TypeKind kind = is_kw(p, &t, KW_STRUCT) ? TY_STRUCT : TY_UNION;
    630       Attr* anon_attrs = NULL;
    631       if (tagged_ty || acc.saw_explicit_type) {
    632         perr(p, "conflicting type specifiers (struct/union mixed)");
    633       }
    634       advance(p);
    635       tagged_ty = parse_struct_or_union(p, kind, &anon_attrs);
    636       attr_list_append(&out->attrs, anon_attrs);
    637       acc.saw_explicit_type = 1;
    638       seen = 1;
    639       continue;
    640     }
    641     if (is_kw(p, &t, KW_ENUM)) {
    642       Attr* anon_attrs = NULL;
    643       if (tagged_ty || acc.saw_explicit_type) {
    644         perr(p, "conflicting type specifiers (enum mixed)");
    645       }
    646       advance(p);
    647       tagged_ty = parse_enum(p, &anon_attrs);
    648       attr_list_append(&out->attrs, anon_attrs);
    649       acc.saw_explicit_type = 1;
    650       seen = 1;
    651       continue;
    652     }
    653     if (is_kw(p, &t, KW_VOID)) {
    654       acc.saw_void = 1;
    655       acc.saw_explicit_type = 1;
    656       advance(p);
    657       seen = 1;
    658     } else if (is_kw(p, &t, KW_CHAR)) {
    659       acc.saw_char = 1;
    660       acc.saw_explicit_type = 1;
    661       advance(p);
    662       seen = 1;
    663     } else if (is_kw(p, &t, KW_INT)) {
    664       acc.saw_int = 1;
    665       acc.saw_explicit_type = 1;
    666       advance(p);
    667       seen = 1;
    668     } else if (is_kw(p, &t, KW_SHORT)) {
    669       acc.saw_short = 1;
    670       acc.saw_explicit_type = 1;
    671       advance(p);
    672       seen = 1;
    673     } else if (is_kw(p, &t, KW_LONG)) {
    674       acc.long_count++;
    675       acc.saw_explicit_type = 1;
    676       advance(p);
    677       seen = 1;
    678     } else if (is_kw(p, &t, KW_SIGNED)) {
    679       acc.saw_signed = 1;
    680       acc.saw_explicit_type = 1;
    681       advance(p);
    682       seen = 1;
    683     } else if (is_kw(p, &t, KW_UNSIGNED)) {
    684       acc.saw_unsigned = 1;
    685       acc.saw_explicit_type = 1;
    686       advance(p);
    687       seen = 1;
    688     } else if (is_kw(p, &t, KW_BOOL)) {
    689       acc.saw_bool = 1;
    690       acc.saw_explicit_type = 1;
    691       advance(p);
    692       seen = 1;
    693     } else if (is_kw(p, &t, KW_FLOAT) || is_kw(p, &t, KW_FLOAT16)) {
    694       acc.saw_float = 1;
    695       acc.saw_explicit_type = 1;
    696       advance(p);
    697       seen = 1;
    698     } else if (is_kw(p, &t, KW_DOUBLE)) {
    699       acc.saw_double = 1;
    700       acc.saw_explicit_type = 1;
    701       advance(p);
    702       seen = 1;
    703     } else if (t.kind == TOK_IDENT && t.v.ident == p->sym_int128) {
    704       acc.saw_int128 = 1;
    705       acc.saw_explicit_type = 1;
    706       advance(p);
    707       seen = 1;
    708     } else if (t.kind == TOK_IDENT && t.v.ident == p->sym_int128_t) {
    709       acc.saw_int128 = 1;
    710       acc.saw_signed = 1;
    711       acc.saw_explicit_type = 1;
    712       advance(p);
    713       seen = 1;
    714     } else if (t.kind == TOK_IDENT && t.v.ident == p->sym_uint128_t) {
    715       acc.saw_int128 = 1;
    716       acc.saw_unsigned = 1;
    717       acc.saw_explicit_type = 1;
    718       advance(p);
    719       seen = 1;
    720     } else if (is_kw(p, &t, KW_STATIC)) {
    721       if (storage_seen) perr(p, "multiple storage-class specifiers");
    722       storage_seen = 1;
    723       out->storage_explicit = 1;
    724       out->storage = DS_STATIC;
    725       advance(p);
    726       seen = 1;
    727     } else if (is_kw(p, &t, KW_EXTERN)) {
    728       if (storage_seen) perr(p, "multiple storage-class specifiers");
    729       storage_seen = 1;
    730       out->storage_explicit = 1;
    731       out->storage = DS_EXTERN;
    732       advance(p);
    733       seen = 1;
    734     } else if (is_kw(p, &t, KW_CONST)) {
    735       out->quals |= Q_CONST;
    736       advance(p);
    737       seen = 1;
    738     } else if (is_kw(p, &t, KW_VOLATILE)) {
    739       out->quals |= Q_VOLATILE;
    740       advance(p);
    741       seen = 1;
    742     } else if (is_kw(p, &t, KW_RESTRICT)) {
    743       out->quals |= Q_RESTRICT;
    744       advance(p);
    745       seen = 1;
    746     } else if (is_kw(p, &t, KW_ATOMIC)) {
    747       Tok n = peek1(p);
    748       if (is_punct(&n, '(')) {
    749         const Type* inner;
    750         if (tagged_ty || acc.saw_explicit_type) {
    751           perr(p, "conflicting type specifiers (_Atomic(T) mixed)");
    752         }
    753         advance(p); /* `_Atomic` */
    754         advance(p); /* `(` */
    755         inner = parse_type_name(p);
    756         expect_punct(p, ')', "')' after _Atomic type");
    757         validate_atomic_operand(p, inner);
    758         tagged_ty = type_qualified(p->pool, inner, Q_ATOMIC);
    759         acc.saw_explicit_type = 1;
    760         seen = 1;
    761         continue;
    762       }
    763       out->quals |= Q_ATOMIC;
    764       advance(p);
    765       seen = 1;
    766     } else if (is_kw(p, &t, KW_TYPEDEF)) {
    767       if (storage_seen) perr(p, "multiple storage-class specifiers");
    768       storage_seen = 1;
    769       out->storage_explicit = 1;
    770       out->storage = DS_TYPEDEF;
    771       advance(p);
    772       seen = 1;
    773     } else if (is_kw(p, &t, KW_ALIGNAS)) {
    774       u32 a = 0;
    775       advance(p); /* `_Alignas` */
    776       expect_punct(p, '(', "'(' after _Alignas");
    777       if (starts_type_name(p, &p->cur)) {
    778         const Type* tn = parse_type_name(p);
    779         a = c_abi_alignof(p->abi, tn);
    780       } else {
    781         i64 v = eval_const_int(p, tok_loc(&p->cur));
    782         if (v < 0) perr(p, "_Alignas requires a non-negative alignment");
    783         a = (u32)v;
    784       }
    785       if (a != 0 && !is_power_of_two_u32(a)) {
    786         perr(p, "_Alignas requires a power-of-two alignment");
    787       }
    788       expect_punct(p, ')', "')' after _Alignas argument");
    789       if (a > out->align) out->align = a;
    790       seen = 1;
    791     } else if (is_kw(p, &t, KW_INLINE)) {
    792       out->flags |= DF_INLINE;
    793       advance(p);
    794       seen = 1;
    795     } else if (is_kw(p, &t, KW_THREAD_LOCAL)) {
    796       out->flags |= DF_THREAD;
    797       advance(p);
    798       seen = 1;
    799     } else if (is_kw(p, &t, KW_NORETURN)) {
    800       out->flags |= DF_NORETURN;
    801       advance(p);
    802       seen = 1;
    803     } else if (is_kw(p, &t, KW_REGISTER)) {
    804       if (storage_seen) perr(p, "multiple storage-class specifiers");
    805       storage_seen = 1;
    806       out->storage_explicit = 1;
    807       out->storage = DS_REGISTER;
    808       advance(p);
    809       seen = 1;
    810     } else if (is_kw(p, &t, KW_AUTO)) {
    811       if (storage_seen) perr(p, "multiple storage-class specifiers");
    812       storage_seen = 1;
    813       out->storage_explicit = 1;
    814       out->storage = DS_AUTO;
    815       advance(p);
    816       seen = 1;
    817     } else if (!acc.saw_explicit_type && !tagged_ty && t.kind == TOK_IDENT &&
    818                ident_kw(p, t.v.ident) == KW_NONE) {
    819       if (t.v.ident == p->sym_b_va_list) {
    820         if (!p->type_b_va_list)
    821           p->type_b_va_list = c_abi_va_list_type(p->abi, p->pool);
    822         tagged_ty = p->type_b_va_list;
    823         acc.saw_explicit_type = 1;
    824         advance(p);
    825         seen = 1;
    826         continue;
    827       }
    828       SymEntry* e = scope_lookup(p, t.v.ident);
    829       if (e && e->kind == SEK_TYPEDEF) {
    830         tagged_ty = e->type;
    831         if (e->vla_byte_slot != FRAME_SLOT_NONE) {
    832           out->vla_byte_slot = e->vla_byte_slot;
    833           out->vla_bounds = e->vla_bounds;
    834         }
    835         acc.saw_explicit_type = 1;
    836         advance(p);
    837         seen = 1;
    838         continue;
    839       }
    840       break;
    841     } else {
    842       break;
    843     }
    844   }
    845   if (seen) {
    846     if (tagged_ty) {
    847       out->type = tagged_ty;
    848     } else {
    849       out->type = resolve_type_specs(p, &acc, loc);
    850       if (!out->type) {
    851         out->type = ty_int(p);
    852       }
    853     }
    854     out->type = attrs_apply_type_mode(p, out->type, out->attrs);
    855     if (out->type && out->quals) {
    856       out->type = type_qualified(p->pool, out->type,
    857                                  (u16)(out->type->qual | out->quals));
    858     }
    859   }
    860   return seen;
    861 }
    862 
    863 /* ============================================================
    864  * struct / union / enum
    865  * ============================================================ */
    866 
    867 int find_field(KitCompiler* abi, Pool* pool, const Type* rec, Sym name,
    868                const Type** out_type, u32* out_offset,
    869                const Field** out_field) {
    870   if (!rec || (rec->kind != TY_STRUCT && rec->kind != TY_UNION)) return 0;
    871   const ABIRecordLayout* L = c_abi_record_layout(abi, pool, rec);
    872   if (!L) return 0;
    873   for (u16 i = 0; i < rec->rec.nfields; ++i) {
    874     const Field* f = &rec->rec.fields[i];
    875     if (f->name == name && name != 0) {
    876       *out_type = f->type;
    877       *out_offset = L->fields[i].offset;
    878       *out_field = f;
    879       return 1;
    880     }
    881     if ((f->flags & FIELD_ANON) &&
    882         (f->type->kind == TY_STRUCT || f->type->kind == TY_UNION)) {
    883       const Type* inner_ty = NULL;
    884       u32 inner_off = 0;
    885       const Field* inner_f = NULL;
    886       if (find_field(abi, pool, f->type, name, &inner_ty, &inner_off,
    887                      &inner_f)) {
    888         *out_type = inner_ty;
    889         *out_offset = L->fields[i].offset + inner_off;
    890         *out_field = inner_f;
    891         return 1;
    892       }
    893     }
    894   }
    895   return 0;
    896 }
    897 
    898 typedef struct MemberNameSeen {
    899   Sym name;
    900   struct MemberNameSeen* next;
    901 } MemberNameSeen;
    902 
    903 static int member_name_seen(MemberNameSeen* names, Sym name) {
    904   for (; names; names = names->next) {
    905     if (names->name == name) return 1;
    906   }
    907   return 0;
    908 }
    909 
    910 static void member_name_add(Parser* p, MemberNameSeen** names, Sym name) {
    911   MemberNameSeen* n;
    912   if (!name) return;
    913   n = arena_new(p->pool->arena, MemberNameSeen);
    914   if (!n) perr(p, "out of memory tracking struct members");
    915   n->name = name;
    916   n->next = *names;
    917   *names = n;
    918 }
    919 
    920 static void validate_and_add_field(Parser* p, TypeRecordBuilder* b,
    921                                    const DeclSpecs* specs, Field* f,
    922                                    MemberNameSeen** names, u32* field_count,
    923                                    int* saw_flexible) {
    924   int is_flexible =
    925       f->type && f->type->kind == TY_ARRAY && f->type->arr.incomplete;
    926   validate_decl_type_constraints(p, specs, f->type, /*is_function=*/0,
    927                                  /*is_member=*/1);
    928   if ((f->flags & FIELD_BITFIELD) && specs->align) {
    929     perr(p, "_Alignas is invalid on bit-field");
    930   }
    931   if (f->name && member_name_seen(*names, f->name)) {
    932     perr(p, "duplicate member name");
    933   }
    934   if (*saw_flexible) perr(p, "flexible array member must be last");
    935   if (is_flexible) {
    936     if (*field_count == 0)
    937       perr(p, "flexible array member cannot be only member");
    938     f->flags |= FIELD_FLEXIBLE_ARRAY;
    939     *saw_flexible = 1;
    940   }
    941   member_name_add(p, names, f->name);
    942   type_record_field(b, *f);
    943   ++*field_count;
    944 }
    945 
    946 static void parse_member_decls(Parser* p, TypeRecordBuilder* b) {
    947   MemberNameSeen* names = NULL;
    948   u32 field_count = 0;
    949   int saw_flexible = 0;
    950   while (!is_punct(&p->cur, '}') && p->cur.kind != TOK_EOF) {
    951     DeclSpecs specs;
    952     if (!parse_decl_specs(p, &specs)) {
    953       perr(p, "expected member declaration");
    954     }
    955     if (is_punct(&p->cur, ';')) {
    956       if (specs.type &&
    957           (specs.type->kind == TY_STRUCT || specs.type->kind == TY_UNION)) {
    958         Field f;
    959         memset(&f, 0, sizeof f);
    960         f.name = 0;
    961         f.type = specs.type;
    962         f.flags = FIELD_ANON;
    963         validate_and_add_field(p, b, &specs, &f, &names, &field_count,
    964                                &saw_flexible);
    965         advance(p);
    966         continue;
    967       }
    968       perr(p, "declaration without declarator must be anonymous aggregate");
    969     }
    970     for (;;) {
    971       Sym mname = 0;
    972       SrcLoc mloc = tok_loc(&p->cur);
    973       const Type* mty;
    974       Field f;
    975       memset(&f, 0, sizeof f);
    976       if (is_punct(&p->cur, ':')) {
    977         advance(p);
    978         if (!type_is_int(specs.type)) perr(p, "bit-field has non-integer type");
    979         i64 w = eval_const_int(p, mloc);
    980         if (w < 0) perr(p, "negative bit-field width");
    981         if (w > (i64)c_abi_sizeof(p->abi, specs.type) * 8) {
    982           perr(p, "bit-field width exceeds its type width");
    983         }
    984         f.name = 0;
    985         f.type = specs.type;
    986         f.bitfield_width = (u16)w;
    987         f.flags = FIELD_BITFIELD;
    988         if (w == 0) f.flags |= FIELD_ZERO_WIDTH;
    989         attrs_to_field(specs.attrs, &f);
    990         if (specs.align > f.align_override) f.align_override = (u16)specs.align;
    991         validate_and_add_field(p, b, &specs, &f, &names, &field_count,
    992                                &saw_flexible);
    993         if (!accept_punct(p, ',')) break;
    994         continue;
    995       }
    996       Attr* mattrs = NULL;
    997       mty = parse_declarator_full_ex(p, specs.type, /*allow_abstract=*/0,
    998                                      &mname, &mloc, &mattrs);
    999       if (accept_punct(p, ':')) {
   1000         if (!type_is_int(mty)) perr(p, "bit-field has non-integer type");
   1001         i64 w = eval_const_int(p, mloc);
   1002         if (w < 0) perr(p, "negative bit-field width");
   1003         if (w == 0 && mname != 0)
   1004           perr(p, "zero-width bit-field must be unnamed");
   1005         if (w > (i64)c_abi_sizeof(p->abi, mty) * 8) {
   1006           perr(p, "bit-field width exceeds its type width");
   1007         }
   1008         f.name = mname;
   1009         f.type = mty;
   1010         f.bitfield_width = (u16)w;
   1011         f.flags = FIELD_BITFIELD;
   1012         if (w == 0) f.flags |= FIELD_ZERO_WIDTH;
   1013       } else {
   1014         f.name = mname;
   1015         f.type = mty;
   1016         f.flags = FIELD_NONE;
   1017       }
   1018       attrs_to_field(specs.attrs, &f);
   1019       attrs_to_field(mattrs, &f);
   1020       {
   1021         Attr* trailing = NULL;
   1022         parse_attrs_into(p, &trailing);
   1023         attrs_to_field(trailing, &f);
   1024       }
   1025       if (specs.align > f.align_override) f.align_override = (u16)specs.align;
   1026       validate_and_add_field(p, b, &specs, &f, &names, &field_count,
   1027                              &saw_flexible);
   1028       if (!accept_punct(p, ',')) break;
   1029     }
   1030     expect_punct(p, ';', "';' after struct member declaration");
   1031   }
   1032 }
   1033 
   1034 const Type* parse_struct_or_union(Parser* p, TypeKind kind,
   1035                                   Attr** anon_attrs_out) {
   1036   Sym tag_name = 0;
   1037   SrcLoc tag_loc;
   1038   TagDeclKind tdk = (kind == TY_STRUCT) ? TAG_STRUCT : TAG_UNION;
   1039   Attr* rec_attrs = NULL;
   1040   parse_attrs_into(p, &rec_attrs);
   1041   tag_loc = tok_loc(&p->cur);
   1042   if (p->cur.kind == TOK_IDENT && ident_kw(p, p->cur.v.ident) == KW_NONE) {
   1043     tag_name = p->cur.v.ident;
   1044     advance(p);
   1045   }
   1046   int has_body = is_punct(&p->cur, '{');
   1047   if (!has_body && tag_name == 0) {
   1048     perr(p, "expected tag name or '{' after struct/union");
   1049   }
   1050   if (!has_body) {
   1051     TagEntry* e = tag_lookup(p, tag_name);
   1052     if (e) {
   1053       if (e->kind != tdk) {
   1054         perr(p, "use of tag with wrong kind (struct vs union)");
   1055       }
   1056       attr_list_append(&e->attrs, rec_attrs);
   1057       return e->type;
   1058     }
   1059     {
   1060       TagId tid = type_tag_new(p->pool, tdk, tag_name, tag_loc);
   1061       Type* t = type_record_forward(p->pool, kind, tid, tag_name);
   1062       TagEntry* te = tag_define(p, tag_name, tdk, t, /*complete=*/0);
   1063       attr_list_append(&te->attrs, rec_attrs);
   1064       return t;
   1065     }
   1066   }
   1067   Type* target = NULL;
   1068   TagEntry* existing = tag_name ? tag_lookup_local(p, tag_name) : NULL;
   1069   TagEntry* te = NULL;
   1070   if (existing) {
   1071     if (existing->kind != tdk) {
   1072       perr(p, "tag redeclared with wrong kind");
   1073     }
   1074     if (existing->complete) {
   1075       perr(p, "redefinition of tag");
   1076     }
   1077     target = existing->type;
   1078     te = existing;
   1079   } else {
   1080     TagId tid = type_tag_new(p->pool, tdk, tag_name, tag_loc);
   1081     target = type_record_forward(p->pool, kind, tid, tag_name);
   1082     if (tag_name) {
   1083       te = tag_define(p, tag_name, tdk, target, /*complete=*/0);
   1084     }
   1085   }
   1086   if (te) {
   1087     attr_list_append(&te->attrs, rec_attrs);
   1088   } else if (anon_attrs_out) {
   1089     attr_list_append(anon_attrs_out, rec_attrs);
   1090   }
   1091   expect_punct(p, '{', "'{' to start aggregate body");
   1092   TypeRecordOpts begin_opts;
   1093   memset(&begin_opts, 0, sizeof begin_opts);
   1094   {
   1095     u32 pack_align = pp_pack_alignment(p->pp);
   1096     if (pack_align > 65535u) pack_align = 65535u;
   1097     begin_opts.max_align = (u16)pack_align;
   1098   }
   1099   attrs_to_record_opts(rec_attrs, &begin_opts);
   1100   TypeRecordBuilder* b = type_record_begin_ex(p->pool, kind, target->rec.tag_id,
   1101                                               tag_name, begin_opts);
   1102   parse_member_decls(p, b);
   1103   expect_punct(p, '}', "'}' after aggregate body");
   1104   TypeRecordOpts trailing_opts;
   1105   memset(&trailing_opts, 0, sizeof trailing_opts);
   1106   {
   1107     Attr* trailing_attrs = NULL;
   1108     parse_attrs_into(p, &trailing_attrs);
   1109     attrs_to_record_opts(trailing_attrs, &trailing_opts);
   1110     if (te) {
   1111       attr_list_append(&te->attrs, trailing_attrs);
   1112     } else if (anon_attrs_out) {
   1113       attr_list_append(anon_attrs_out, trailing_attrs);
   1114     }
   1115   }
   1116   {
   1117     const Type* fresh = type_record_end(p->pool, b);
   1118     target->rec.packed = fresh->rec.packed;
   1119     target->rec.max_align = fresh->rec.max_align;
   1120     target->rec.align_override = fresh->rec.align_override;
   1121     type_record_install(target, (Field*)fresh->rec.fields, fresh->rec.nfields);
   1122   }
   1123   if (trailing_opts.packed) target->rec.packed = 1;
   1124   if (trailing_opts.align_override > target->rec.align_override)
   1125     target->rec.align_override = trailing_opts.align_override;
   1126   if (te) te->complete = 1;
   1127   return target;
   1128 }
   1129 
   1130 const Type* parse_enum(Parser* p, Attr** anon_attrs_out) {
   1131   Sym tag_name = 0;
   1132   SrcLoc tag_loc;
   1133   Attr* rec_attrs = NULL;
   1134   parse_attrs_into(p, &rec_attrs);
   1135   tag_loc = tok_loc(&p->cur);
   1136   if (p->cur.kind == TOK_IDENT && ident_kw(p, p->cur.v.ident) == KW_NONE) {
   1137     tag_name = p->cur.v.ident;
   1138     advance(p);
   1139   }
   1140   int has_body = is_punct(&p->cur, '{');
   1141   if (!has_body && tag_name == 0) {
   1142     perr(p, "expected tag name or '{' after enum");
   1143   }
   1144   if (!has_body) {
   1145     TagEntry* e = tag_lookup(p, tag_name);
   1146     if (e && e->kind == TAG_ENUM) {
   1147       attr_list_append(&e->attrs, rec_attrs);
   1148       return e->type;
   1149     }
   1150     if (e) {
   1151       perr(p, "tag redeclared with wrong kind");
   1152     }
   1153     perr(p, "enum tag declared without definition");
   1154   }
   1155   TagId tid = type_tag_new(p->pool, TAG_ENUM, tag_name, tag_loc);
   1156   const Type* et = type_enum(p->pool, tid, tag_name, ty_int(p));
   1157   expect_punct(p, '{', "'{'");
   1158   i64 next_val = 0;
   1159   for (;;) {
   1160     Sym name;
   1161     SrcLoc nloc = tok_loc(&p->cur);
   1162     SymEntry* e;
   1163     if (p->cur.kind != TOK_IDENT || ident_kw(p, p->cur.v.ident) != KW_NONE) {
   1164       perr(p, "expected enumerator name");
   1165     }
   1166     name = p->cur.v.ident;
   1167     advance(p);
   1168     i64 val = next_val;
   1169     if (accept_punct(p, '=')) {
   1170       val = eval_const_int(p, nloc);
   1171     }
   1172     if (scope_lookup_current(p, name)) {
   1173       perr(p, "redefinition of enumerator");
   1174     }
   1175     e = scope_define(p, name, SEK_ENUM_CST, et);
   1176     e->v.enum_value = val;
   1177     next_val = val + 1;
   1178     if (!accept_punct(p, ',')) break;
   1179     if (is_punct(&p->cur, '}')) break;
   1180   }
   1181   expect_punct(p, '}', "'}' after enumerator list");
   1182   parse_attrs_into(p, &rec_attrs);
   1183   if (tag_name) {
   1184     TagEntry* existing = tag_lookup_local(p, tag_name);
   1185     if (existing) {
   1186       if (existing->kind != TAG_ENUM) {
   1187         perr(p, "tag redeclared with wrong kind");
   1188       }
   1189       if (existing->complete) {
   1190         perr(p, "redefinition of enum tag");
   1191       }
   1192       existing->complete = 1;
   1193       attr_list_append(&existing->attrs, rec_attrs);
   1194     } else {
   1195       TagEntry* te = tag_define(p, tag_name, TAG_ENUM, (Type*)et,
   1196                                 /*complete=*/1);
   1197       attr_list_append(&te->attrs, rec_attrs);
   1198     }
   1199   } else if (anon_attrs_out) {
   1200     attr_list_append(anon_attrs_out, rec_attrs);
   1201   }
   1202   return et;
   1203 }
   1204 
   1205 /* ============================================================
   1206  * starts_type_name, parse_pointer_layer, parse_type_name
   1207  * ============================================================ */
   1208 
   1209 int starts_type_name(const Parser* p, const Tok* t) {
   1210   if (t->kind != TOK_IDENT) return 0;
   1211   CKw k = ident_kw(p, t->v.ident);
   1212   switch (k) {
   1213     case KW_VOID:
   1214     case KW_CHAR:
   1215     case KW_SHORT:
   1216     case KW_INT:
   1217     case KW_LONG:
   1218     case KW_FLOAT:
   1219     case KW_FLOAT16:
   1220     case KW_DOUBLE:
   1221     case KW_SIGNED:
   1222     case KW_UNSIGNED:
   1223     case KW_BOOL:
   1224     case KW_STRUCT:
   1225     case KW_UNION:
   1226     case KW_ENUM:
   1227     case KW_CONST:
   1228     case KW_VOLATILE:
   1229     case KW_RESTRICT:
   1230     case KW_ATOMIC:
   1231     case KW_STATIC:
   1232     case KW_EXTERN:
   1233     case KW_INLINE:
   1234     case KW_NORETURN:
   1235     case KW_REGISTER:
   1236     case KW_AUTO:
   1237     case KW_TYPEDEF:
   1238     case KW_ALIGNAS:
   1239     case KW_THREAD_LOCAL:
   1240       return 1;
   1241     case KW_NONE: {
   1242       if (t->v.ident == p->sym_b_va_list) return 1;
   1243       if (t->v.ident == p->sym_int128 || t->v.ident == p->sym_int128_t ||
   1244           t->v.ident == p->sym_uint128_t)
   1245         return 1;
   1246       SymEntry* e = scope_lookup((Parser*)p, t->v.ident);
   1247       return e && e->kind == SEK_TYPEDEF;
   1248     }
   1249     default:
   1250       return 0;
   1251   }
   1252 }
   1253 
   1254 const Type* parse_pointer_layer(Parser* p, const Type* base) {
   1255   while (accept_punct(p, '*')) {
   1256     u16 q = 0;
   1257     base = type_ptr(p->pool, base);
   1258     for (;;) {
   1259       if (accept_kw(p, KW_CONST)) {
   1260         q |= Q_CONST;
   1261         continue;
   1262       }
   1263       if (accept_kw(p, KW_VOLATILE)) {
   1264         q |= Q_VOLATILE;
   1265         continue;
   1266       }
   1267       if (accept_kw(p, KW_RESTRICT)) {
   1268         q |= Q_RESTRICT;
   1269         continue;
   1270       }
   1271       if (accept_kw(p, KW_ATOMIC)) {
   1272         q |= Q_ATOMIC;
   1273         continue;
   1274       }
   1275       if (starts_attr(p)) {
   1276         parse_and_discard_attributes(p);
   1277         continue;
   1278       }
   1279       break;
   1280     }
   1281     if (q) base = type_qualified(p->pool, base, q);
   1282   }
   1283   return base;
   1284 }
   1285 
   1286 const Type* parse_type_name(Parser* p) {
   1287   DeclSpecs specs;
   1288   Sym dummy_name = 0;
   1289   SrcLoc dummy_loc = {0, 0, 0};
   1290   if (!parse_decl_specs(p, &specs)) {
   1291     perr(p, "expected type-name");
   1292   }
   1293   return parse_declarator_full(p, specs.type, /*allow_abstract=*/1, &dummy_name,
   1294                                &dummy_loc);
   1295 }
   1296 
   1297 /* ============================================================
   1298  * Declarator suffix helpers
   1299  * (DeclSuffix / DSuffKind defined in parse_priv.h)
   1300  * ============================================================ */
   1301 
   1302 static void param_vla_record_bound(Parser* p, Tok* toks, u32 ntoks,
   1303                                    int has_expr) {
   1304   ParamVLABoundExpr* b;
   1305   if (p->param_vla_bound_len >=
   1306       sizeof p->param_vla_bounds / sizeof p->param_vla_bounds[0]) {
   1307     perr(p, "too many VLA dimensions per parameter");
   1308   }
   1309   b = &p->param_vla_bounds[p->param_vla_bound_len++];
   1310   b->toks = toks;
   1311   b->ntoks = ntoks;
   1312   b->has_expr = (u8)(has_expr ? 1 : 0);
   1313 }
   1314 
   1315 static void parse_param_array_bound(Parser* p, DeclSuffix* out) {
   1316   Tok* toks = NULL;
   1317   u32 ntoks = 0;
   1318   u32 cap = 0;
   1319   int depth = 1;
   1320   int has_expr = 0;
   1321 
   1322   out->incomplete = 1;
   1323   if (accept_punct(p, ']')) {
   1324     param_vla_record_bound(p, NULL, 0, 0);
   1325     return;
   1326   }
   1327   while (depth > 0) {
   1328     Tok t = p->cur;
   1329     if (t.kind == TOK_EOF) {
   1330       perr(p, "unexpected EOF in parameter array bound");
   1331     }
   1332     if (is_punct(&t, '[')) {
   1333       ++depth;
   1334     } else if (is_punct(&t, ']')) {
   1335       --depth;
   1336       if (depth == 0) break;
   1337     }
   1338     if (ntoks == cap) {
   1339       u32 nc = cap ? cap * 2u : 4u;
   1340       Tok* nb = arena_array(p->pool->arena, Tok, nc);
   1341       if (toks && ntoks) memcpy(nb, toks, sizeof(Tok) * ntoks);
   1342       toks = nb;
   1343       cap = nc;
   1344     }
   1345     toks[ntoks++] = t;
   1346     has_expr = 1;
   1347     advance(p);
   1348   }
   1349   if (ntoks == 1 && toks[0].kind == TOK_PUNCT && toks[0].v.punct == '*') {
   1350     has_expr = 0;
   1351   }
   1352   if (ntoks == 1 && toks[0].kind == TOK_NUM) {
   1353     i64 count = parse_int_literal(p, &toks[0]);
   1354     if (count <= 0 || (u64)count > UINT32_MAX) {
   1355       perr(p, "array bound must be positive");
   1356     }
   1357     out->count = (u32)count;
   1358     out->incomplete = 0;
   1359     out->vla = 0;
   1360     expect_punct(p, ']', "']' after array size");
   1361     return;
   1362   }
   1363   param_vla_record_bound(p, toks, ntoks, has_expr);
   1364   expect_punct(p, ']', "']' after array size");
   1365 }
   1366 
   1367 int parse_decl_suffix(Parser* p, DeclSuffix* out) {
   1368   if (accept_punct(p, '[')) {
   1369     out->kind = DS_ARRAY;
   1370     out->count = 0;
   1371     out->incomplete = 0;
   1372     out->vla = 0;
   1373     for (;;) {
   1374       if (accept_kw(p, KW_STATIC) || accept_kw(p, KW_CONST) ||
   1375           accept_kw(p, KW_VOLATILE) || accept_kw(p, KW_RESTRICT) ||
   1376           accept_kw(p, KW_ATOMIC)) {
   1377         continue;
   1378       }
   1379       break;
   1380     }
   1381     if (p->in_param_decl) {
   1382       parse_param_array_bound(p, out);
   1383       return 1;
   1384     }
   1385     if (accept_punct(p, ']')) {
   1386       out->incomplete = 1;
   1387       return 1;
   1388     }
   1389     {
   1390       Tok t = p->cur;
   1391       int is_const_start = (t.kind == TOK_NUM || t.kind == TOK_CHR);
   1392       if (p->cur_func_name == 0 && t.kind == TOK_PUNCT && t.v.punct == '(')
   1393         is_const_start = 1;
   1394       if (t.kind == TOK_FLT) {
   1395         perr(p, "array bound requires integer type");
   1396       }
   1397       if (!is_const_start && t.kind == TOK_IDENT) {
   1398         SymEntry* e = scope_lookup(p, t.v.ident);
   1399         if (e && e->kind == SEK_ENUM_CST) is_const_start = 1;
   1400         if (!is_const_start) {
   1401           CKw k = ident_kw(p, t.v.ident);
   1402           if (k == KW_SIZEOF || k == KW_ALIGNOF) is_const_start = 1;
   1403         }
   1404       }
   1405       if (is_const_start) {
   1406         SrcLoc cloc = tok_loc(&p->cur);
   1407         i64 v = eval_const_int(p, cloc);
   1408         if (v < 0) perr(p, "negative array size");
   1409         out->count = (u32)v;
   1410       } else {
   1411         FrameSlotDesc fsd;
   1412         if (p->vla_pending_count_len >=
   1413             sizeof p->vla_pending_count_slots /
   1414                 sizeof p->vla_pending_count_slots[0]) {
   1415           perr(p, "too many VLA dimensions per declarator");
   1416         }
   1417         out->vla = 1;
   1418         memset(&fsd, 0, sizeof fsd);
   1419         fsd.type = ty_size_t(p);
   1420         fsd.size = c_abi_sizeof(p->abi, fsd.type);
   1421         fsd.align = c_abi_alignof(p->abi, fsd.type);
   1422         fsd.kind = FS_LOCAL;
   1423         out->vla_count_slot = pcg_local(p, &fsd);
   1424         parse_assign_expr(p);
   1425         to_rvalue(p);
   1426         pcg_push_local_typed(p, out->vla_count_slot, fsd.type);
   1427         pcg_swap(p);
   1428         coerce_top_to_lvalue(p);
   1429         pcg_store(p);
   1430         pcg_drop(p);
   1431         p->vla_pending = 1;
   1432         ++p->vla_mark;
   1433         p->vla_pending_count_slot = out->vla_count_slot;
   1434         p->vla_pending_count_slots[p->vla_pending_count_len++] =
   1435             out->vla_count_slot;
   1436       }
   1437     }
   1438     expect_punct(p, ']', "']' after array size");
   1439     return 1;
   1440   }
   1441   if (accept_punct(p, '(')) {
   1442     out->kind = DS_FUNC;
   1443     out->params = NULL;
   1444     out->nparams = 0;
   1445     out->variadic = 0;
   1446     parse_param_list(p, &out->params, &out->nparams, &out->variadic);
   1447     expect_punct(p, ')', "')' after parameter list");
   1448     return 1;
   1449   }
   1450   return 0;
   1451 }
   1452 
   1453 const Type* apply_decl_suffix(Parser* p, const Type* base,
   1454                               const DeclSuffix* s) {
   1455   if (s->kind == DS_ARRAY) {
   1456     if (base && base->kind == TY_FUNC) {
   1457       perr(p, "array of function type is invalid");
   1458     }
   1459     if (base && base->kind == TY_VOID) {
   1460       perr(p, "array of void type is invalid");
   1461     }
   1462     return type_array(p->pool, base, s->count, s->incomplete || s->vla);
   1463   }
   1464   {
   1465     const Type** ptypes = NULL;
   1466     if (base && base->kind == TY_ARRAY) {
   1467       perr(p, "function returning array is invalid");
   1468     }
   1469     if (base && base->kind == TY_FUNC) {
   1470       perr(p, "function returning function is invalid");
   1471     }
   1472     if (s->nparams) {
   1473       ptypes =
   1474           (const Type**)arena_array(p->pool->arena, const Type*, s->nparams);
   1475       for (u16 i = 0; i < s->nparams; ++i) ptypes[i] = s->params[i].type;
   1476     }
   1477     return type_func(p->pool, base, ptypes, s->nparams, (int)s->variadic);
   1478   }
   1479 }
   1480 
   1481 /* ============================================================
   1482  * parse_declarator_full, parse_declarator_full_ex, parse_declarator
   1483  * ============================================================ */
   1484 
   1485 const Type* parse_declarator_full(Parser* p, const Type* base,
   1486                                   int allow_abstract, Sym* name_out,
   1487                                   SrcLoc* loc_out) {
   1488   return parse_declarator_full_ex(p, base, allow_abstract, name_out, loc_out,
   1489                                   NULL);
   1490 }
   1491 
   1492 const Type* parse_declarator_full_ex(Parser* p, const Type* base,
   1493                                      int allow_abstract, Sym* name_out,
   1494                                      SrcLoc* loc_out, Attr** attrs_out) {
   1495   return parse_declarator_full_info(p, base, allow_abstract, name_out, loc_out,
   1496                                     attrs_out, NULL);
   1497 }
   1498 
   1499 const Type* parse_declarator_full_info(Parser* p, const Type* base,
   1500                                        int allow_abstract, Sym* name_out,
   1501                                        SrcLoc* loc_out, Attr** attrs_out,
   1502                                        DeclaratorInfo* info_out) {
   1503   Attr* local_attrs = NULL;
   1504   Sym asm_label = 0;
   1505   base = parse_pointer_layer(p, base);
   1506 
   1507   Sym name = 0;
   1508   SrcLoc nloc = {0, 0, 0};
   1509   u8 nptrs_inner = 0;
   1510   u16 inner_quals[8];
   1511   u8 nptrs_nested = 0;
   1512   u16 nested_quals[8];
   1513   int has_inner_parens = 0;
   1514   DeclSuffix inner_suffs[8];
   1515   int n_inner_suffs = 0;
   1516 
   1517   if (is_punct(&p->cur, '(')) {
   1518     Tok n = peek1(p);
   1519     int is_inner = 0;
   1520     if (is_punct(&n, '*')) {
   1521       is_inner = 1;
   1522     } else if (n.kind == TOK_IDENT && ident_kw(p, n.v.ident) == KW_NONE) {
   1523       SymEntry* e = scope_lookup(p, n.v.ident);
   1524       if (!(e && e->kind == SEK_TYPEDEF)) is_inner = 1;
   1525     }
   1526     if (is_inner) {
   1527       has_inner_parens = 1;
   1528       advance(p); /* '(' */
   1529       while (accept_punct(p, '*')) {
   1530         u16 q = 0;
   1531         if (nptrs_inner >= 8) perr(p, "too many pointer levels");
   1532         for (;;) {
   1533           if (accept_kw(p, KW_CONST)) {
   1534             q |= Q_CONST;
   1535             continue;
   1536           }
   1537           if (accept_kw(p, KW_VOLATILE)) {
   1538             q |= Q_VOLATILE;
   1539             continue;
   1540           }
   1541           if (accept_kw(p, KW_RESTRICT)) {
   1542             q |= Q_RESTRICT;
   1543             continue;
   1544           }
   1545           if (accept_kw(p, KW_ATOMIC)) {
   1546             q |= Q_ATOMIC;
   1547             continue;
   1548           }
   1549           if (starts_attr(p) || starts_asm_label(p)) {
   1550             parse_and_discard_attrs_or_asm(p);
   1551             continue;
   1552           }
   1553           break;
   1554         }
   1555         inner_quals[nptrs_inner++] = q;
   1556       }
   1557       if (p->cur.kind == TOK_IDENT && ident_kw(p, p->cur.v.ident) == KW_NONE) {
   1558         name = p->cur.v.ident;
   1559         nloc = tok_loc(&p->cur);
   1560         advance(p);
   1561       } else if (is_punct(&p->cur, '(')) {
   1562         Tok nn = peek1(p);
   1563         if (!is_punct(&nn, '*')) {
   1564           if (!allow_abstract) perr(p, "expected declarator name");
   1565           goto after_inner_name;
   1566         }
   1567         advance(p); /* nested '(' */
   1568         while (accept_punct(p, '*')) {
   1569           u16 q = 0;
   1570           if (nptrs_nested >= 8) perr(p, "too many pointer levels");
   1571           for (;;) {
   1572             if (accept_kw(p, KW_CONST)) {
   1573               q |= Q_CONST;
   1574               continue;
   1575             }
   1576             if (accept_kw(p, KW_VOLATILE)) {
   1577               q |= Q_VOLATILE;
   1578               continue;
   1579             }
   1580             if (accept_kw(p, KW_RESTRICT)) {
   1581               q |= Q_RESTRICT;
   1582               continue;
   1583             }
   1584             if (accept_kw(p, KW_ATOMIC)) {
   1585               q |= Q_ATOMIC;
   1586               continue;
   1587             }
   1588             if (starts_attr(p) || starts_asm_label(p)) {
   1589               parse_and_discard_attrs_or_asm(p);
   1590               continue;
   1591             }
   1592             break;
   1593           }
   1594           nested_quals[nptrs_nested++] = q;
   1595         }
   1596         if (p->cur.kind == TOK_IDENT &&
   1597             ident_kw(p, p->cur.v.ident) == KW_NONE) {
   1598           name = p->cur.v.ident;
   1599           nloc = tok_loc(&p->cur);
   1600           advance(p);
   1601         } else if (!allow_abstract) {
   1602           perr(p, "expected declarator name");
   1603         }
   1604         parse_and_discard_attrs_or_asm(p);
   1605         expect_punct(p, ')', "')' after nested declarator");
   1606       } else if (!allow_abstract) {
   1607         perr(p, "expected declarator name");
   1608       }
   1609     after_inner_name:
   1610       parse_and_discard_attrs_or_asm(p);
   1611       while (n_inner_suffs < 8) {
   1612         if (!parse_decl_suffix(p, &inner_suffs[n_inner_suffs])) break;
   1613         ++n_inner_suffs;
   1614         parse_and_discard_attrs_or_asm(p);
   1615       }
   1616       expect_punct(p, ')', "')' after inner declarator");
   1617     }
   1618   }
   1619 
   1620   if (!has_inner_parens) {
   1621     if (p->cur.kind == TOK_IDENT && ident_kw(p, p->cur.v.ident) == KW_NONE) {
   1622       name = p->cur.v.ident;
   1623       nloc = tok_loc(&p->cur);
   1624       advance(p);
   1625     } else if (!allow_abstract) {
   1626       perr(p, "expected declarator name");
   1627     }
   1628   }
   1629 
   1630   parse_attrs_and_asm_into(p, attrs_out, &local_attrs, &asm_label);
   1631 
   1632   DeclSuffix suffs[8];
   1633   int nsuffs = 0;
   1634   DeclSuffix* final_fn_suff = NULL;
   1635   if (info_out) memset(info_out, 0, sizeof *info_out);
   1636   while (nsuffs < 8) {
   1637     if (!parse_decl_suffix(p, &suffs[nsuffs])) break;
   1638     ++nsuffs;
   1639     parse_attrs_and_asm_into(p, attrs_out, &local_attrs, &asm_label);
   1640   }
   1641   base = attrs_apply_type_mode(p, base, attrs_out ? *attrs_out : local_attrs);
   1642   if (nsuffs == 8 && (is_punct(&p->cur, '[') || is_punct(&p->cur, '('))) {
   1643     perr(p, "too many declarator suffixes (raise the cap if needed)");
   1644   }
   1645   if (n_inner_suffs > 0 && inner_suffs[0].kind == DS_FUNC) {
   1646     final_fn_suff = &inner_suffs[0];
   1647   } else if (n_inner_suffs == 0 && nptrs_inner == 0 && nsuffs > 0 &&
   1648              suffs[0].kind == DS_FUNC) {
   1649     final_fn_suff = &suffs[0];
   1650   }
   1651   for (int i = nsuffs - 1; i >= 0; --i) {
   1652     base = apply_decl_suffix(p, base, &suffs[i]);
   1653   }
   1654 
   1655   for (int i = (int)nptrs_inner - 1; i >= 0; --i) {
   1656     base = type_ptr(p->pool, base);
   1657     if (inner_quals[i]) {
   1658       base = type_qualified(p->pool, base, inner_quals[i]);
   1659     }
   1660   }
   1661 
   1662   for (int i = n_inner_suffs - 1; i >= 0; --i) {
   1663     base = apply_decl_suffix(p, base, &inner_suffs[i]);
   1664   }
   1665 
   1666   for (int i = (int)nptrs_nested - 1; i >= 0; --i) {
   1667     base = type_ptr(p->pool, base);
   1668     if (nested_quals[i]) {
   1669       base = type_qualified(p->pool, base, nested_quals[i]);
   1670     }
   1671   }
   1672 
   1673   if (info_out && base && base->kind == TY_FUNC && final_fn_suff) {
   1674     info_out->fn_params = final_fn_suff->params;
   1675     info_out->fn_nparams = final_fn_suff->nparams;
   1676     info_out->fn_variadic = final_fn_suff->variadic;
   1677   }
   1678   if (info_out) info_out->asm_label = asm_label;
   1679   if (name_out) *name_out = name;
   1680   if (loc_out) *loc_out = nloc;
   1681   return base;
   1682 }
   1683 
   1684 const Type* parse_declarator(Parser* p, const Type* base, Sym* name_out,
   1685                              SrcLoc* loc_out) {
   1686   return parse_declarator_full(p, base, /*allow_abstract=*/0, name_out,
   1687                                loc_out);
   1688 }
   1689 
   1690 /* ============================================================
   1691  * complete_incomplete_array
   1692  * ============================================================ */
   1693 
   1694 const Type* complete_incomplete_array(Parser* p, const Type* ty) {
   1695   const Type* elem;
   1696   if (!ty || ty->kind != TY_ARRAY || !ty->arr.incomplete) return ty;
   1697   elem = ty->arr.elem;
   1698   if (p->cur.kind == TOK_STR &&
   1699       string_literal_initializes_array(p, elem, &p->cur)) {
   1700     Tok t = p->cur;
   1701     size_t n = 0;
   1702     u8* bytes = decode_string_literal(p, &t, &n);
   1703     u32 elem_size = c_abi_sizeof(p->abi, elem);
   1704     kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
   1705                                            bytes, 0);
   1706     return type_array(p->pool, elem, elem_size ? (u32)(n / elem_size) : 0,
   1707                       /*incomplete=*/0);
   1708   }
   1709   if (is_punct(&p->cur, '{')) {
   1710     u32 cnt;
   1711     record_braced_block(p);
   1712     cnt = count_recorded_top_level_items(p->replay, p->replay_len);
   1713     if (cnt == 1 && p->replay_len >= 3 && p->replay[1].kind == TOK_STR &&
   1714         string_literal_initializes_array(p, elem, &p->replay[1])) {
   1715       Tok t = p->replay[1];
   1716       size_t n = 0;
   1717       u8* bytes = decode_string_literal(p, &t, &n);
   1718       u32 elem_size = c_abi_sizeof(p->abi, elem);
   1719       kit_compiler_context(p->c)->heap->free(kit_compiler_context(p->c)->heap,
   1720                                              bytes, 0);
   1721       cnt = elem_size ? (u32)(n / elem_size) : 0;
   1722     }
   1723     replay_rewind(p);
   1724     return type_array(p->pool, elem, cnt, /*incomplete=*/0);
   1725   }
   1726   perr(p, "initializer cannot complete incomplete array type");
   1727 }