aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/stmt.zc
diff options
context:
space:
mode:
authorGravatar zinc <zinc@downsta.ir> 2026-10-15 21:44:40 +0330
committerGravatar zinc <zinc@downsta.ir> 2026-10-15 21:44:40 +0330
commitf3dcfd9805e1bd23b002f648d4391ec397122d9c (patch)
tree91acab7da09c9225a2d838791d70e5c2e7db54b9 /src/compiler/stmt.zc
parentmerge work/small-oob: bytes test out-of-bounds read (diff)
parentexamples/actors_demo: print the fan-out replies in worker order, not arrival ... (diff)
merge work/known-bugs: constant-expression precedence, local const in constant expressions, duplicate case labels, unterminated strings, droppable cycles in one collection, js vm exit, docs, actors_demo orderHEADmain
Diffstat (limited to 'src/compiler/stmt.zc')
-rw-r--r--src/compiler/stmt.zc14
1 files changed, 12 insertions, 2 deletions
diff --git a/src/compiler/stmt.zc b/src/compiler/stmt.zc
index 007306c..79e5fb8 100644
--- a/src/compiler/stmt.zc
+++ b/src/compiler/stmt.zc
@@ -144,7 +144,7 @@ int localdecl(int typed) {
newsz = -1; newleaf = 0; if (tk == T_NUM) nomagic = 1;
if (t && t[0] == TY_DYN && is_op(s_lb)) c = array_dynamic_literal(t); else c = expr();
rval(); nomagic = 0; kc = xconst && !xfloat;
- if (kc) ltag[i] = ltag[i] | LCONST;
+ if (kc) { ltag[i] = ltag[i] | LCONST; lkval[i] = xcval; }
if (c == C_FRESH) { lnsz[i] = newsz; lleaf[i] = newleaf; if (drop_tail == here) local_dropset[i] = 1; }
if (t) fcoerce(t);
vaddr(i);
@@ -566,11 +566,19 @@ int casebody(int s0, int live0) {
live = 0;
return 0;
}
+// a case label seen twice in one switch is an error (spec 4.7.2): the second
+// arm could never run. the first 256 labels of a switch are checked.
+int case_seen(word seen, int n, int v) {
+ int i = 0;
+ while (i < n) { if (seen[i] == v) { serr("duplicate case label"); return n; } i++; }
+ if (n < 256) { seen[n] = v; n++; }
+ return n;
+}
// compile a switch statement.
int kw_switch() {
int sl = tline;
int save = nloc, tmp, c, s0, live0, defent = -1, skip, nxt, bj, v, a = -1, st, tg = 0, cov = 0, gi, nb = 0, j, arm, bi;
- word[8] pbn; word[8] pbl;
+ word[8] pbn; word[8] pbl; word[256] seen; int nseen = 0;
stmtonly();
next();
expect(s_lp); c = expr(); st = xty; rval(); plainuse(c); expect(s_rp);
@@ -609,6 +617,7 @@ int kw_switch() {
expect(s_rp);
if (nb && nb != pm_nf[gi]) serr("a case binds every field of its member"); // member() with no names matches by tag (spec 4.7.3)
v = pm_tag[gi];
+ nseen = case_seen(seen, nseen, v);
if (v < 63) cov = cov | (1 << v);
laddr(lslot[tmp]); op(O_LD); op(O_LD); lit(v); op(O_SUB);
bj = fixnew(hole(), bj); op(O_JZ);
@@ -633,6 +642,7 @@ int kw_switch() {
} else {
while (1) {
v = cexpr();
+ nseen = case_seen(seen, nseen, v);
if (tg && v >= 0 && v < 63) cov = cov | (1 << v);
laddr(lslot[tmp]); op(O_LD);
if (tg) op(O_LD);