edhall@randvax.ARPA (Ed Hall) (01/11/84)
------------------------------------ This bug may affect all pre-5.0USG C compilers, and perhaps earlier 5.0USG compilers as well. The below fix only works for PCC-derived compilers (such as the BSD VAX C compiler). Index: usr.lib/ccom 4.2BSD 4.1BSD 3.0USG Description: When assignement operators such as *= are used with an integer Left-Hand Side and a floating-point expression on the Right- Hand Side, results are incorrect. For example: int i = 6; i *= .5; leaves a value of 0 in i, rather than 3. The +=, -=, and /= operators are similarly affected. Caused by: Conversion of RHS of assignment to type of LHS before application of the operator. Fixed by: The fix is in two parts. First, the automatic forcing of type conversion to the LHS of an assignment op must be shut off in appropriate circumstances. This requires a change to tymatch() in mip/trees.c: 1031c1031,1035 < if( t != t2 || o==CAST ) p->in.right = makety( p->in.right, tu, 0, (int)tu ); --- > if( o==CAST || (t != t2 > && ( (dope[o]&(FLOFLG|ASGOPFLG)) != (FLOFLG|ASGOPFLG) > || t != INT || (t2 != DOUBLE && t2 != FLOAT) )) ) { > p->in.right = makety( p->in.right, tu, 0, (int)tu ); > } This causes certain assignment ops (+=, -=, *=, /=, i.e. the ones appropriate in floating-point) to remain in the parse tree without `balanced' operand types. When these get to code-generation the compiler would break unless the template table had the proper pieces added to it. Thus, in pcc/table.c: 712a713,729 > > /* begin new stuff */ > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TDOUBLE, > NAREG, RLEFT|RESCC, > " cvtZLd AL,A1\n OD2 AR,A1\n cvtdZL A1,AL\n", > > ASG OPFLOAT, INAREG|FOREFF|FORCC, > SAREG|AWD, TWORD|TCHAR|TSHORT, > SAREG|AWD, TFLOAT, > NAREG, RLEFT|RESCC, > " cvtZLf AL,A1\n OF2 AR,A1\n cvtfZL A1,AL\n", > > /* end new stuff */ > -Ed Hall Rand Corporation Santa Monica, CA decvax!randvax!edhall (UUCP) edhall@rand-unix (ARPA)
myunive@nsc.UUCP (Jay Zelitzky) (01/14/84)
.......... Everyone has been missing another case where there is a problem: int /= unsigned; will do an integer divide instead of the correct unsigned divide. This will result in a different value in some cases. For example: (2^32-1)/2 will equal some large number if the division is done unsigned and 0 if the division is signed. A slight variation of the previously posted fix will also fix this case. Jay Zelitzky {menlo70,fortune}!nsc!myunive
msc@qubix.UUCP (Mark Callow) (01/17/84)
Can we please close this seemingly endless discussion. God (dmr) spoke some weeks ago confirming that it is indeed a bug for x *= y to differ from x = x * y. What more is there to discuss except actual fixes for various compilers? -- From the Tardis of Mark Callow msc@qubix.UUCP, decwrl!qubix!msc@Berkeley.ARPA ...{decvax,ucbvax,ihnp4}!decwrl!qubix!msc, ...{ittvax,amd70}!qubix!msc