[net.bugs.4bsd] Parenthesis error in 4.2bsd c compiler includes apologies

donn@utah-cs.UUCP (08/29/84)

Shot my mouth off again...  There is a terrible error in the fix I
suggested for the float to int cast bug which I sent out earlier.  The
cure was worse than the disease...  The compiler failed to make sure
that the new treatment was being applied only to constants; it was
throwing expressions and variables away!  Fortunately the compiler
detects the inconsistency and bitches about it.  Here is (with crossed
fingers) the correct fix, in clocal() in pcc/local.c:

------------------------------------------------------------------------
*** /tmp/,RCSt1024490	Wed Aug 29 00:25:09 1984
--- local.c	Wed Aug 29 00:22:25 1984
***************
*** 85,91
  	case SCONV:
  		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
  		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
! 		if( m != ml ) break;
  
  		/* now, look for conversions downwards */
  

--- 85,99 -----
  	case SCONV:
  		m = (p->in.type == FLOAT || p->in.type == DOUBLE );
  		ml = (p->in.left->in.type == FLOAT || p->in.left->in.type == DOUBLE );
! 		if ( p->in.left->in.op == FCON && ml && !m ) {
! 			/* float type to int type */
! 			r = block( ICON, NULL, NULL, INT, 0, 0 );
! 			r->tn.lval = (int) p->in.left->fpn.dval;
! 			r->tn.rval = NONAME;
! 			p->in.left->in.op = FREE;
! 			p->in.left = r;
! 			}
! 		else if ( ml != m ) break;
  
  		/* now, look for conversions downwards */
  
------------------------------------------------------------------------

This will teach me to release a fix without testing it on something
big...  I DID remember to test the new compiler after installing the
update, and tested it again after (recklessly?) installing the next
fix.  Speaking of which...

Alain Williams provides a program which the 4.2 BSD C compiler generates
incorrect code for:

------------------------------------------------------------------------
main()
{
	unsigned u, u2;
	int	m_7 = -7, two = 2, i, j;
	u = m_7;
	i = (u % two);
	j = ((int) u) % two;
	printf("%u %d %d %d %d\n", u, (int) (u%two), i, (u%two), j);
}
------------------------------------------------------------------------

When run this program prints

	4294967289 -1 1 1 -1

when it should print

	4294967289 1 1 1 -1

instead.

The problem is in the routine hardops() which finds unsigned division
and remainder operations and replaces them with calls to subroutines.
It should be looking at the types of the operands to determine if
unsigned arithmetic is necessary, but it instead considers the type of
the operator, which in this case was changed by a cast.  The following
change to hardops() in pcc/local2.c fixes this problem:

------------------------------------------------------------------------
*** /tmp/,RCSt1024433	Wed Aug 29 00:15:59 1984
--- local2.c	Tue Aug 28 22:32:43 1984
***************
*** 1041,1048
  	register TWORD t;
  
  	o = p->in.op;
! 	t = p->in.type;
! 	if( t!=UNSIGNED && t!=ULONG ) return;
  
  	for( f=opfunc; f->fop; f++ ) {
  		if( o==f->fop ) goto convert;

--- 1041,1050 -----
  	register TWORD t;
  
  	o = p->in.op;
! 	if( ! (optype(o)==BITYPE &&
! 	       (ISUNSIGNED(p->in.left->in.type) ||
! 		ISUNSIGNED(p->in.right->in.type))) )
! 		return;
  
  	for( f=opfunc; f->fop; f++ ) {
  		if( o==f->fop ) goto convert;
------------------------------------------------------------------------

Hope I don't have to backtrack again,

Donn Seeley    University of Utah CS Dept    donn@utah-cs.arpa
40 46' 6"N 111 50' 34"W    (801) 581-5668    decvax!utah-cs!donn