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:
@@ -1282,6 +1282,11 @@ cbinop(Checker *c, Node *n)
|
||||
return ty_i64;
|
||||
if (!type_isnum(l) || !type_isnum(r))
|
||||
return err(c, n->pos, "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 (n->op == TK_PERCENT && (!type_isint(l) || !type_isint(r)))
|
||||
return err(c, n->pos, "modulo on non-integer type");
|
||||
return unify_arith(c, n->pos, l, r);
|
||||
case TK_AMP: case TK_PIPE: case TK_CARET: case TK_LSHIFT:
|
||||
case TK_RSHIFT:
|
||||
@@ -2016,6 +2021,32 @@ cexpr(Checker *c, Node *n)
|
||||
!assignable_addrfn(c, l, n->rhs))
|
||||
err(c, n->pos, "cannot assign %s to %s",
|
||||
type_name(c->a, r), type_name(c->a, l));
|
||||
/* Compound ops carry their binary op's operand class (harec
|
||||
* check.c binarithm): += -= *= /= need numeric operands,
|
||||
* %= modulo-integer, the bitwise/shift five integer. The
|
||||
* assignability check above cannot see the op, so `f %= x`
|
||||
* and `s += "x"` passed and cgen's fallback plain-stored the
|
||||
* rhs, silently dropping the operation. */
|
||||
if (n->op != TK_ASSIGN && l != ty_err && r != ty_err) {
|
||||
switch (n->op) {
|
||||
case TK_PLUSEQ: case TK_MINUSEQ: case TK_STAREQ:
|
||||
case TK_SLASHEQ:
|
||||
if (!type_isnum(l) || !type_isnum(r))
|
||||
err(c, n->pos, "arithmetic on "
|
||||
"non-numeric type");
|
||||
break;
|
||||
case TK_PERCENTEQ:
|
||||
if (!type_isint(l) || !type_isint(r))
|
||||
err(c, n->pos, "modulo on "
|
||||
"non-integer type");
|
||||
break;
|
||||
default:
|
||||
if (!type_isint(l) || !type_isint(r))
|
||||
err(c, n->pos, "bitwise on "
|
||||
"non-integer type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* #120: `w = 1.0` narrows the rhs literal to the lvalue's f32. */
|
||||
coerce_floatlit(n->rhs, l);
|
||||
/* #258: `s = arr` borrows the array as a full slice.
|
||||
|
||||
Reference in New Issue
Block a user