From be43babc1886fc5efee898b2a3d0285012e511fb Mon Sep 17 00:00:00 2001 From: zinc Date: Thu, 15 Oct 2026 22:15:38 +0330 Subject: definite assignment: reading a local before it is initialized is a compile error (spec 4.1.5, b.1.9) track linited per local alongside the ownership state; snapshots, exit records and joins carry it, and a join keeps a local set only when every reaching path set it. x = e, a declaration initializer, &x (out-parameter), a full array initializer, or using an aggregate as an address set a local; field and element writes do not set the aggregate. while/for bodies that may run zero times do not count; do/while does. compiler, runtime, std, actor and lsp sources initialize the locals the rule flagged; zc0 accepts = {} brace lists (zeroed). tests: tests/errors/uninit_*.zc, tests/conformance/4-statements/uninit_*.zc --- src/tools/zc0.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'src/tools') diff --git a/src/tools/zc0.c b/src/tools/zc0.c index 229734c..07a5933 100644 --- a/src/tools/zc0.c +++ b/src/tools/zc0.c @@ -824,14 +824,24 @@ static void stmt(void) if (nw >= 0 || accept("let") || accept("var")) { if (nw < 0) nw = 1; do { - Loc *l = &lo[nlo++]; strcpy(l->name, ident()); l->arr = 0; - if (nw > 1) { l->slot = nslot; nslot += nw; l->arr = 1; } + Loc *l = &lo[nlo++]; strcpy(l->name, ident()); l->arr = 0; int asz = 1; + if (nw > 1) { l->slot = nslot; nslot += nw; l->arr = 1; asz = nw; } else { - if (accept("[")) { n = cexpr(); expect("]"); nslot += n; l->slot = nslot - n; l->arr = 1; } + if (accept("[")) { n = cexpr(); expect("]"); nslot += n; l->slot = nslot - n; l->arr = 1; asz = n; } else l->slot = nslot++; } l->flt = 0; l->dstr = tstr && !l->arr; l->str = l->dstr; - if (accept("=")) { expr(); rval(); laddr(l->slot); op(O_ST); l->flt = xf; l->str = xs || l->dstr; } + if (accept("=")) { + if (is("{")) { /* brace initializer: skip the list and zero the slots */ + int depth = 0, zi; + do { + if (is("{")) { depth++; next(); } + else if (is("}")) { depth--; next(); } + else next(); + } while (depth > 0 && tk); + for (zi = 0; zi < asz; zi++) { lit(0); laddr(l->slot + zi); op(O_ST); } + } else { expr(); rval(); laddr(l->slot); op(O_ST); l->flt = xf; l->str = xs || l->dstr; } + } } while (accept(",")); expect(";"); return; } @@ -1106,10 +1116,15 @@ static void top1(void) else if (accept("[")) { k = (int)cexpr(); expect("]"); } if (k > 1) { a = here; while (k--) emit(0); add(n, K_GARR, a); + if (accept("=")) { /* = {} or = {...}: already zeroed */ + if (!is("{")) die("a global array initializer is a brace list"); + { int depth = 0; do { if (is("{")) { depth++; next(); } else if (is("}")) { depth--; next(); } else next(); } while (depth > 0 && tk); } + } } else { a = here; gs = add(n, K_GVAR, a); gs->str = gstr; emit(0); if (accept("=")) { - if (tk == T_STR) { int i, l = (int)strlen(ts); img[a - GORG] = here; for (i = 0; i < l; i++) emit((unsigned char)ts[i]); emit(0); next(); } + if (is("{")) { int depth = 0; do { if (is("{")) { depth++; next(); } else if (is("}")) { depth--; next(); } else next(); } while (depth > 0 && tk); } + else if (tk == T_STR) { int i, l = (int)strlen(ts); img[a - GORG] = here; for (i = 0; i < l; i++) emit((unsigned char)ts[i]); emit(0); next(); } else if (tk == T_BSTR) { int d = bstrwords((const unsigned char *)ts, (long)strlen(ts)); img[a - GORG] = d; gs->str = 1; next(); } else img[a - GORG] = cexpr(); } -- cgit v1.2.3