wcc: stamp computed enum-member value-exprs

A computed enum member — B = A + 4, RW = R | W, sibling/chained backref —
left its value-expr node nil-typed: enumvalfold folds the constant but never
stamps the expr, and since enum members are not installed as scope idents the
sibling backref resolves to nothing, so BOTH the N_BIN/N_UN wrapper and the
backref N_IDENT go nil (literal members are fine). Stamp the value-expr subtree
(only-nil) to the enum's underlying storage type via a new
stampenumvals/stampnilexpr pass on the N_TENUM branch. Mirrors harec checking
each member value-expr at the underlying type (ref/harec/src/check.c:4419).

A prerequisite for arming the wwstage asserttyped bail. Checker-only — the
value folds to a constant at every use site and in cgen, so the node's type_
is never read by codegen; 990-997 byte-id hold. Extends the 901 gap-corpus
with 901_enum_corpus.ww.
This commit is contained in:
2026-05-28 08:07:19 +09:00
parent 360b58b267
commit 3252bd1709
5 changed files with 158 additions and 1 deletions

View File

@@ -25,6 +25,7 @@
* C abort intrinsic callee utf8 8
* D module-leaf == type/fn name fnmatch 0 (closed)
* D module-leaf == type/fn name random 0 (closed)
* E computed enum-member value-expr enum_corpus 0 (closed)
*
* Exit code of wwdump_ww is intentionally not gated: the diagnostics
* land on stderr regardless of the run's success, and arming the bail
@@ -116,6 +117,8 @@ main(void)
"D module-leaf == type/fn name", 0 },
{ "lib/math/random/random_test.combined.ww",
"D module-leaf == type/fn name", 0 },
{ "test/wcc/901_enum_corpus.ww",
"E computed enum-member value-expr", 0 },
{ NULL, NULL, 0 },
};
@@ -151,6 +154,6 @@ main(void)
return 1;
}
printf("asserttyped_gap: ww-stage checker warn set matches manifest "
"on %d gap-corpus fixtures (C pinned, A+B+D closed)\n", n);
"on %d gap-corpus fixtures (C pinned, A+B+D+E closed)\n", n);
return 0;
}

View File

@@ -0,0 +1,37 @@
// 901_enum_corpus — computed enum-member value-expr gap fixture for
// the 901 asserttyped net (class E). Each computed member leaves its
// value-expr (N_BIN / N_UN / sibling-backref N_IDENT) type_=nil until
// the checker's stampenumvals fills the subtree at the enum's
// underlying type. Mirrors the 759_check_enum_fold rows plus the 994
// in-source `RW = R | W` shape (enum u8). Literal + auto-increment
// members never warned (resolvewalk's post-order exprtype stamps the
// leaf), so the literal-only enum is a control: it must stay 0.
package main;
type sib = enum i32 { A = 7, B = A };
type un = enum i32 { NEG = -7, R = NEG + 14 };
type unl = enum i32 { TIL = ~(-8), PLU = +7 };
type arith = enum i32 {
A = 3,
ADD = A + 4,
SUB = A - 1,
MUL = A * 2,
DIV = A / 3,
MOD = A % 2,
};
type bits = enum i32 {
A = 5,
AND = A & 3,
IOR = A | 2,
XOR = A ^ 1,
SHL = A << 2,
SHR = A >> 1,
};
type chain = enum i32 { A = 1, B = A + 1, C = B + 1, D = C + 4 };
type mode = enum u8 { RD = 1u8, WR = 2u8, RW = RD | WR };
type lit = enum i32 { X = 7, Y = 9, Z = 11 };
fn main() i32 = {
return chain.D: i32 + mode.RW: i32;
};