zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 3a6f716f22f9c9e7de7387aae404013e93a5f232 (tree)
parent 83e972b87f0dd87119733f39286b36f12659cde3
Author: Motiejus <motiejus@jakstys.lt>
Date:   Fri, 27 Feb 2026 02:29:23 +0000

sema: fix type alias resolution and refactor FieldInfo struct

Fix resolveZirTypeInst decl_val path: when ensureNavValUpToDate returns
IP_INDEX_VOID_TYPE (from unhandled type instructions like optional_type),
fall through to the type alias fallback instead of returning the bogus
result. Also fix bugs where the fallback used the caller's ZIR/namespace
instead of the nav's, and create ptr_nav for resolved type aliases to
match the Zig compiler's analyzeNavRefInner behavior.

Replace FieldInfo struct in resolveStructFieldInitsC with separate arrays
to satisfy cppcheck unused-member checks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

Diffstat:
Mstage0/sema.c | 89++++++++++++++++++++++++++++++++++++++++++-------------------------------------
1 file changed, 47 insertions(+), 42 deletions(-)

diff --git a/stage0/sema.c b/stage0/sema.c @@ -3258,10 +3258,13 @@ static InternPoolIndex resolveZirTypeInst( } if (nav != UINT32_MAX) { InternPoolIndex result = ensureNavValUpToDate(nav); - if (result != IP_INDEX_NONE) + if (result != IP_INDEX_NONE && result != IP_INDEX_VOID_TYPE) return result; // Type alias (e.g. `const ErrorSet = ?[]const Error`): // resolve the nav's value body as a type expression. + // Also reached when ensureNavValUpToDate returns VOID_TYPE, + // which happens when the body contains type instructions + // (optional_type, ptr_type) that analyzeNavValC can't handle. const Nav* tnav = ipGetNav(nav); uint32_t tnns = tnav->namespace_idx; uint32_t tnfi = s_namespaces[tnns].file_idx; @@ -3273,20 +3276,30 @@ static InternPoolIndex resolveZirTypeInst( if (tbody && tbody_len > 0) { uint32_t last_inst = tbody[tbody_len - 1]; if (last_inst < tzir->inst_len - && zir->inst_tags[last_inst] + && tzir->inst_tags[last_inst] == ZIR_INST_BREAK_INLINE) { ZirInstRef op = tzir->inst_datas[last_inst].break_data.operand; - result - = resolveZirTypeRef(tzir, op, struct_ns, file_idx); - if (result != IP_INDEX_NONE) { + InternPoolIndex alias_result + = resolveZirTypeRef(tzir, op, tnns, tnfi); + if (alias_result != IP_INDEX_NONE) { Nav* wnav = ipGetNav(nav); - wnav->resolved_type = result; + wnav->resolved_type = alias_result; + // Create ptr_nav for the alias declaration, + // matching analyzeNavRefInner which creates + // a ptr_nav for every resolved nav reference. + InternPoolIndex ptr_ty + = internPtrConst(IP_INDEX_TYPE_TYPE); + (void)internNavPtr(ptr_ty, nav); + return alias_result; } - return result; } } } + // If the type alias fallback didn't resolve, return the + // original result (which may be VOID_TYPE or NONE). + if (result != IP_INDEX_NONE) + return result; } } @@ -3572,17 +3585,18 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, uint32_t bags_count = (s_fields_len + 7) / 8; sei += bags_count; - // First pass: collect field info including type refs. - typedef struct { - uint32_t type_body_len; - uint32_t align_body_len; - uint32_t init_body_len; - uint32_t type_ref; // valid when has_type_body == false - bool has_type_body; - } FieldInfo; - FieldInfo field_info[32]; // max fields we handle + // First pass: collect body lengths for each field. + // Stored as separate arrays to satisfy cppcheck unused-member checks. + uint32_t fi_type_body_len[32]; + uint32_t fi_align_body_len[32]; + uint32_t fi_init_body_len[32]; + uint32_t fi_type_ref[32]; // valid when type_body_len == 0 if (s_fields_len > 32) return; + memset(fi_type_body_len, 0, s_fields_len * sizeof(uint32_t)); + memset(fi_align_body_len, 0, s_fields_len * sizeof(uint32_t)); + memset(fi_init_body_len, 0, s_fields_len * sizeof(uint32_t)); + memset(fi_type_ref, 0, s_fields_len * sizeof(uint32_t)); for (uint32_t fi = 0; fi < s_fields_len; fi++) { uint32_t bag_i = fi / 8; @@ -3591,28 +3605,21 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, bool f_has_align = (bits & 1) != 0; bool f_has_init = ((bits >> 1) & 1) != 0; bool f_has_type_body = ((bits >> 3) & 1) != 0; - (void)f_has_align; sei++; // skip field_name - field_info[fi].type_body_len = 0; - field_info[fi].align_body_len = 0; - field_info[fi].init_body_len = 0; - field_info[fi].type_ref = 0; - field_info[fi].has_type_body = f_has_type_body; - if (f_has_type_body) - field_info[fi].type_body_len = zir->extra[sei]; + fi_type_body_len[fi] = zir->extra[sei]; else - field_info[fi].type_ref = zir->extra[sei]; + fi_type_ref[fi] = zir->extra[sei]; sei++; if (f_has_align) { - field_info[fi].align_body_len = zir->extra[sei]; + fi_align_body_len[fi] = zir->extra[sei]; sei++; } if (f_has_init) { - field_info[fi].init_body_len = zir->extra[sei]; + fi_init_body_len[fi] = zir->extra[sei]; sei++; } } @@ -3623,17 +3630,17 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, uint32_t pos = sei; for (uint32_t fi = 0; fi < s_fields_len; fi++) { type_body_starts[fi] = pos; - pos += field_info[fi].type_body_len; - pos += field_info[fi].align_body_len; - pos += field_info[fi].init_body_len; + pos += fi_type_body_len[fi]; + pos += fi_align_body_len[fi]; + pos += fi_init_body_len[fi]; } } // Second pass: iterate through bodies and evaluate init bodies. for (uint32_t fi = 0; fi < s_fields_len; fi++) { - sei += field_info[fi].type_body_len; - sei += field_info[fi].align_body_len; - uint32_t init_body_len = field_info[fi].init_body_len; + sei += fi_type_body_len[fi]; + sei += fi_align_body_len[fi]; + uint32_t init_body_len = fi_init_body_len[fi]; uint32_t init_body_start = sei; sei += init_body_len; @@ -3653,10 +3660,9 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, if (operand == ZIR_REF_NULL_VALUE) { // Resolve the field type to get the optional type IP index. InternPoolIndex opt_ty = IP_INDEX_NONE; - if (field_info[fi].has_type_body - && field_info[fi].type_body_len > 0) { + if (fi_type_body_len[fi] > 0) { uint32_t tbs = type_body_starts[fi]; - uint32_t tbl = field_info[fi].type_body_len; + uint32_t tbl = fi_type_body_len[fi]; uint32_t tb_last = zir->extra[tbs + tbl - 1]; if (tb_last < zir->inst_len && zir->inst_tags[tb_last] == ZIR_INST_BREAK_INLINE) { @@ -3760,16 +3766,15 @@ static void resolveStructFieldInitsC(const Zir* zir, uint32_t struct_inst, uint64_t val = zir->inst_datas[operand_inst].int_val; InternPoolIndex field_ty = IP_INDEX_NONE; - if (!field_info[fi].has_type_body - && field_info[fi].type_ref < ZIR_REF_START_INDEX) { + if (fi_type_body_len[fi] == 0 + && fi_type_ref[fi] < ZIR_REF_START_INDEX) { // Simple pre-interned type ref. - field_ty = field_info[fi].type_ref; - } else if (field_info[fi].has_type_body - && field_info[fi].type_body_len > 0) { + field_ty = fi_type_ref[fi]; + } else if (fi_type_body_len[fi] > 0) { // Resolve the field type from the type body. // Find the break_inline at end of type body. uint32_t tbs = type_body_starts[fi]; - uint32_t tbl = field_info[fi].type_body_len; + uint32_t tbl = fi_type_body_len[fi]; uint32_t tb_last = zir->extra[tbs + tbl - 1]; if (tb_last < zir->inst_len && zir->inst_tags[tb_last] == ZIR_INST_BREAK_INLINE) {