wcc: modulo is integer-only; compound ops carry their operand class
Hare's rule (harec check.c binarithm): % and the bitwise/shift five are integer-only; + - * / need numeric operands. ww grouped % with the numeric ops, and compound assigns never op-checked at all, so `a % b` on floats compiled half-lowered (live cs!=ww divergence), `a %= 2.0` plain-stored the rhs (op silently dropped, both stages), and `s += "cd"` garbled str headers. Gate both at the checker, both stages; the cgen float-compound fallbacks and the three unknown- compound legacy defaults (deref/global/local) demote to rule-7 hard stops. 34 compound-on-tagged/str/slice fixtures re-pin from the old cgen "not wired" stops to the earlier checker diagnostics; 3 new reject fixtures pin the closed shapes.
This commit is contained in:
@@ -3069,6 +3069,15 @@ fn binoptype(c: *checker, e: *syntax.node) *syntax.node = {
|
||||
(rtn != nil && !numkindast(c, rtn))) {
|
||||
deffolderr(c, e, "arithmetic on non-numeric type");
|
||||
};
|
||||
// % is integer-only (harec check.c binarithm BIN_MODULO):
|
||||
// floats have no SSE modulo lowering, so an admitted float %
|
||||
// fell through cgen half-lowered (cs!=ww divergence).
|
||||
if (op == syntax.tkind.TK_PERCENT) {
|
||||
if ((ltn != nil && !intkindast(c, ltn)) ||
|
||||
(rtn != nil && !intkindast(c, rtn))) {
|
||||
deffolderr(c, e, "modulo on non-integer type");
|
||||
};
|
||||
};
|
||||
return unifyarith(c, e, ltn, rtn);
|
||||
};
|
||||
if (op == syntax.tkind.TK_AMP || op == syntax.tkind.TK_PIPE ||
|
||||
@@ -6137,6 +6146,34 @@ fn checkassign(c: *checker, n: *syntax.node) void = {
|
||||
};
|
||||
let ltn: *syntax.node = exprtype(c, n.lhs, nil);
|
||||
let rtn: *syntax.node = exprtype(c, n.rhs, nil);
|
||||
// Compound ops carry their binary op's operand class (harec
|
||||
// check.c binarithm): += -= *= /= need numeric operands,
|
||||
// %= modulo-integer, the bitwise/shift five integer. Without
|
||||
// this `f %= x` and `s += "x"` passed and cgen's fallback
|
||||
// plain-stored the rhs, silently dropping the operation.
|
||||
// Mirror cstage cmd/wcc/check.c N_ASSIGN compound gate.
|
||||
if (n.op != syntax.tkind.TK_ASSIGN) {
|
||||
if (n.op == syntax.tkind.TK_PLUSEQ || n.op == syntax.tkind.TK_MINUSEQ ||
|
||||
n.op == syntax.tkind.TK_STAREQ || n.op == syntax.tkind.TK_SLASHEQ) {
|
||||
if ((ltn != nil && !numkindast(c, ltn)) ||
|
||||
(rtn != nil && !numkindast(c, rtn))) {
|
||||
cerr("error: arithmetic on non-numeric type\n");
|
||||
c.errs += 1;
|
||||
};
|
||||
} else { if (n.op == syntax.tkind.TK_PERCENTEQ) {
|
||||
if ((ltn != nil && !intkindast(c, ltn)) ||
|
||||
(rtn != nil && !intkindast(c, rtn))) {
|
||||
cerr("error: modulo on non-integer type\n");
|
||||
c.errs += 1;
|
||||
};
|
||||
} else {
|
||||
if ((ltn != nil && !intkindast(c, ltn)) ||
|
||||
(rtn != nil && !intkindast(c, rtn))) {
|
||||
cerr("error: bitwise on non-integer type\n");
|
||||
c.errs += 1;
|
||||
};
|
||||
}; };
|
||||
};
|
||||
// #120: `w = 1.0` narrows the rhs literal to the lvalue's f32. Mirror
|
||||
// cstage cmd/wcc/check.c N_ASSIGN coerce_floatlit.
|
||||
coercefloatlit(c, n.rhs, ltn);
|
||||
|
||||
Reference in New Issue
Block a user