check: type the N_BIN operand of as in the wwstage
An enum OR-fold under `as` ((m.A|m.B) as u32) was never typed: scruttype resolves IDENT/DOT only, and the post-order restamp then re-derived the folded member literals as untyped_int. The unstamped operand missed cgtypeassert's #27b enum-reinterpret gate and lowered as a phantom tagged assert — unconditional exit 1 at runtime on the wwstage leg. checkisas now types an N_BIN lhs and the N_BIN restamp preserves an existing enum stamp. Graduates the #59.9 stattest pin.
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
package wwfixture;
|
package wwfixture;
|
||||||
|
|
||||||
def protocolversion: i32 = 1;
|
def protocolversion: i32 = 1;
|
||||||
def corpuscount: i32 = 1236;
|
def corpuscount: i32 = 1237;
|
||||||
def errorcount: i32 = 314;
|
def errorcount: i32 = 314;
|
||||||
def compilecount: i32 = 12;
|
def compilecount: i32 = 12;
|
||||||
def runcount: i32 = 144;
|
def runcount: i32 = 145;
|
||||||
def runexitcount: i32 = 766;
|
def runexitcount: i32 = 766;
|
||||||
def nativecount: i32 = 2472;
|
def nativecount: i32 = 2474;
|
||||||
def corpushash: str = "4c8f4a693d2d8193b15f4215610c1d070dc83493b1189af772ca09cad4a69db7";
|
def corpushash: str = "7763f2eb34524f67355114f5bdfbf3f64415152a8ec64060fe32a322bdbe1b24";
|
||||||
|
|
||||||
type directive = enum i32 {
|
type directive = enum i32 {
|
||||||
ERROR = 0,
|
ERROR = 0,
|
||||||
|
|||||||
@@ -3328,6 +3328,22 @@ fn exprtype(c: *checker, e: *syntax.node, hint: *syntax.node) *syntax.node = {
|
|||||||
};
|
};
|
||||||
if (k == syntax.nkind.N_BIN) {
|
if (k == syntax.nkind.N_BIN) {
|
||||||
let tn: *syntax.node = binoptype(c, e);
|
let tn: *syntax.node = binoptype(c, e);
|
||||||
|
// #59.9: checkisas pre-stamps an enum OR-fold (`(m.A|m.B) as
|
||||||
|
// u32`) TY_ENUM and folds the member N_DOTs to int literals;
|
||||||
|
// this post-order revisit re-derives from those now-untyped
|
||||||
|
// literals and clobbered the stamp, so cgtypeassert's #27b
|
||||||
|
// reinterpret gate missed and emitted a phantom tagged assert
|
||||||
|
// (unconditional exit 1). Keep an existing enum stamp; the
|
||||||
|
// returned tnode contract for callers is unchanged.
|
||||||
|
let pre599: *syntax.tinfo = e.type_: *syntax.tinfo;
|
||||||
|
if (pre599 != nil) {
|
||||||
|
let prech: *syntax.tinfo = tichase(pre599);
|
||||||
|
if (prech != nil) {
|
||||||
|
if (prech.kind == syntax.tykind.TY_ENUM) {
|
||||||
|
return tn;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
e.type_ = tinfofornode(c, tn): *void;
|
e.type_ = tinfofornode(c, tn): *void;
|
||||||
return tn;
|
return tn;
|
||||||
};
|
};
|
||||||
@@ -6353,6 +6369,15 @@ fn checkisas(c: *checker, n: *syntax.node) void = {
|
|||||||
if (n.lhs.kind == syntax.nkind.N_TRYPROP || n.lhs.kind == syntax.nkind.N_TRYUNW) {
|
if (n.lhs.kind == syntax.nkind.N_TRYPROP || n.lhs.kind == syntax.nkind.N_TRYUNW) {
|
||||||
st = exprtype(c, n.lhs, nil);
|
st = exprtype(c, n.lhs, nil);
|
||||||
};
|
};
|
||||||
|
// #59.9: an N_BIN operand (`(m.A | m.B) as u32`) was never
|
||||||
|
// typed, so the OR-fold reached cgen unstamped and
|
||||||
|
// cgtypeassert's enum-reinterpret gate (#27b) missed —
|
||||||
|
// lowering a plain enum value as a phantom tagged assert
|
||||||
|
// (unconditional exit 1). cstage types the lhs
|
||||||
|
// unconditionally (cmd/wcc/check.c:2220 cexpr(c, n->lhs)).
|
||||||
|
if (n.lhs.kind == syntax.nkind.N_BIN) {
|
||||||
|
st = exprtype(c, n.lhs, nil);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
let u: *syntax.node = resolvealias(c, unwrapbang(st));
|
let u: *syntax.node = resolvealias(c, unwrapbang(st));
|
||||||
if (u == nil) { return; };
|
if (u == nil) { return; };
|
||||||
|
|||||||
@@ -169,8 +169,13 @@ static const struct ent ents[] = {
|
|||||||
/* #59.7 siphash graduated to M_ID above (#61 fix) */
|
/* #59.7 siphash graduated to M_ID above (#61 fix) */
|
||||||
{ .fixture = "lib/log/logtest.ww",
|
{ .fixture = "lib/log/logtest.ww",
|
||||||
.mode = M_DIVERGE, .cite = "#59.8" },
|
.mode = M_DIVERGE, .cite = "#59.8" },
|
||||||
|
/* #59.9 graduated: the wwstage checker never typed an N_BIN operand
|
||||||
|
* of `as`, so an enum OR-fold reached cgen unstamped and lowered as
|
||||||
|
* a phantom tagged assert (unconditional exit 1). checkisas now
|
||||||
|
* types the N_BIN lhs and the post-order restamp preserves the enum
|
||||||
|
* stamp. Runtime pin: r599_enum_orfold_as. */
|
||||||
{ .fixture = "lib/os/stattest.ww",
|
{ .fixture = "lib/os/stattest.ww",
|
||||||
.mode = M_DIVERGE, .cite = "#59.9" },
|
.mode = M_ID, .cite = "#59.9 graduated by the checkisas N_BIN stamp" },
|
||||||
/* #59.10 stoftest graduated to M_ID above (#62 fix) */
|
/* #59.10 stoftest graduated to M_ID above (#62 fix) */
|
||||||
{ .fixture = "lib/ww/syntax/toktest.ww", .inc = "lib/ww",
|
{ .fixture = "lib/ww/syntax/toktest.ww", .inc = "lib/ww",
|
||||||
.mode = M_ID, .cite = "#59.11 graduated by #146 str==" },
|
.mode = M_ID, .cite = "#59.11 graduated by #146 str==" },
|
||||||
|
|||||||
16
test/wcc/data/r599_enum_orfold_as/case.ww
Normal file
16
test/wcc/data/r599_enum_orfold_as/case.ww
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//ww:run
|
||||||
|
// #59.9: an enum member OR-fold under `as`. The pre-fix wwstage
|
||||||
|
// checker never typed the N_BIN operand, so cgtypeassert's enum
|
||||||
|
// reinterpret gate missed and lowered a phantom tagged assert that
|
||||||
|
// unconditionally exited 1.
|
||||||
|
package main;
|
||||||
|
|
||||||
|
type mask = enum u32 { A = 1, B = 2, C = 4 };
|
||||||
|
|
||||||
|
fn main() i32 = {
|
||||||
|
let w: u32 = (mask.A | mask.B | mask.C) as u32;
|
||||||
|
if (w != 7u32) { return 1; };
|
||||||
|
let v: u32 = (mask.A | mask.C) as u32;
|
||||||
|
if (v != 5u32) { return 2; };
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user