[net.lang.c] SUN C compiler bug?

argv@sri-spam.ARPA (AAAARRRRGGGGv) (03/28/86)

Consider the following routine on the sun:

    char x;
    for(x = 0; x < 128; x++)
	putchar('x');

You would expect to have 128 x's printed on your screen.  but,
on the sun, the variable x is signed and NOT converted to an int
as it is on the vax version of the 4.2 UNIX C compiler.  So, running 
this program on a sun will produce nothing. On the vax, it will print 128 x's. 

Bug with the sun? Maybe...
1) should the programmer know not to compare a size larger than or
equal to the value of the type that would make a signed number negative
(as above) or 2) should the compiler know that all constants should be
taken as literal (or, the assembler should do this) and compared as
such?

Whichever you think should be the "way", remember that the vax has the
same "bug" (?) with intergers:

    int x;
    for(x = 0; x < 4294967296; x ++)
	putchar('x');

this, too will also print nothing because 4294967296 is -1 and 'x' is
signed.  Why is there a difference and who is "wrong"?   well, arguing
for the second example above says that suns assembler is wrong because it
creates code that moves a byte into a register and does a cmpb
(compare byte) intruction where as they should do a cvtbl (convert a
btye to long) and then move into a register and cmpl (compare long).

Supporting argument 1) says that what I just said (above) will fix the
problem with bytes or shorts, but not ints, and that's right. Even on a
vax, you have to make sure that you don't compare with potentially signed
values so the programmer is responsible and should not have created either
of the two cases above.

Let's throw another log into the fire.  Compile the first example with
the -O (code optimizer) flag on the sun. You'll find that a single 'x' 
is printed and nothing more. It actually does one round inside the for loop!
(The vax doesn't do this.) It is definitely a bug when the optimizer
produces different output than without the optimizer.

donn@utah-gr.UUCP (03/29/86)

The code in question:

	char x;
	for(x = 0; x < 128; x++)
		putchar('x');

The Sun compiler I use (Sun release 2.2) does indeed compile this
incorrectly, using a byte compare in the 'for' loop test.  But I
certainly wouldn't want my VAX to print 128 x's on my screen on the
basis of this program, as was claimed.  The local (4.3 BSD) VAX
compiler produces from this source a program that prints infinitely
many x's, because the char variable 'x' wraps around to -128 from 127
and thus never exceeds 128.  This program will print 128 x's only if
your VAX compiler treats char variables as being unsigned by default --
what kind of VAX compiler is that?

Mr. Argv asks:

	[S]hould the programmer know not to compare a size larger than
	or equal to the value of the type that would make a signed
	number negative[?] ...

If I understand this correctly, the answer is 'yes'.  Of course 'lint'
could find cases such as this and complain about them, as it already
complains about 'degenerate unsigned comparisons'.

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

gwyn@BRL.ARPA (03/29/86)

When dissimilar types occur in an expression, they are converted
into comparable types according to rules you can find in K&R,
better in Harbison&Steele, better still in the X3J11 draft.  The
conversion involves widening smaller types, not shrinking fatter
ones.  Since 128 is an (int), the (char) x should have been
widened to (int) before the < comparison.  On the other hand,
you have the problem that signed chars will never widen to
something >= 128 (assuming 8-bit byte), so the loop would never
terminate.  Yes it's a bug, but the code is buggy too.

jsdy@hadron.UUCP (03/29/86)

In article <5418@sri-spam.ARPA> argv@sri-spam.ARPA (AAAARRRRGGGGv) writes:
>    char x;
>    for(x = 0; x < 128; x++)
>	putchar('x');
>on the sun, the variable x is signed and NOT converted to an int ...
>this program on a sun will produce nothing. On the vax, it will print 128 x's. 

It seems pretty clear that 128 is a numeric constant, not a character
constant.  Therefore, x should be converted to an int or unsigned int
(K&R 2.7, A.6.1; X3J11 3.1).  Which one (int or u_int) seems to be
irrelevant, given a character size >= 8 bits.  Unless the int size is
8 bits too, this behaviour is clearly incorrect.

>    int x;
>    for(x = 0; x < 4294967296; x ++)
>	putchar('x');
>this, too will also print nothing because 4294967296 is -1 and 'x' is
>signed.  Why is there a difference and who is "wrong"?

Here, x is clearly a signed integer.  The constant is too long to
fit into an int, and hence (as I've just learned!) is a long int ...
which is the same as an int on VAXen.  x is "promoted" to long int
(ha ha), and the two are compared, with the result you name.  All
kosher, per the standard(s).
-- 

	Joe Yao		hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP}

tachi@koudai.uucp (Hiroshi Tachibana) (03/30/86)

In article <5418@sri-spam.ARPA> argv@sri-spam.UUCP writes:
> 
>     char x;
>     for(x = 0; x < 128; x++)
> 	putchar('x');
> 
> You would expect to have 128 x's printed on your screen.  but,
> on the sun, the variable x is signed and NOT converted to an int
> as it is on the vax version of the 4.2 UNIX C compiler.

I know a similar bug(?) on the Sun C compiler.
Consider the code something like:

	printf("%d\n", (any_expr, 257)) ;
		/*
		 * Of course, it does not mean printf("%d\n", any_expr, 257) ;
		 * (any_expr, 257) is a comma expression
		 */

This should generate output '257' (it is on Vax), but it actually outputs
'1' on any version of Sun as long as I know (release 1.2, 2.2, 3.0).
It interpretes the last component of comma expression as a singed character,
if it is an integer constant.  This is a bug, isn't it?

----
Hiroshi Tachibana
Dept. of C.S., Tokyo Institute of Technology
UUCP: ...!{hplabs,seismo,ihnp4}!kddlab!koudai!tachi

pete@valid.UUCP (Pete Zakel) (04/05/86)

> I know a similar bug(?) on the Sun C compiler.
> Consider the code something like:
> 
> 	printf("%d\n", (any_expr, 257)) ;
> 		/*
> 		 * Of course, it does not mean printf("%d\n", any_expr, 257) ;
> 		 * (any_expr, 257) is a comma expression
> 		 */
> 
> This should generate output '257' (it is on Vax), but it actually outputs
> '1' on any version of Sun as long as I know (release 1.2, 2.2, 3.0).
> It interpretes the last component of comma expression as a singed character,
> if it is an integer constant.  This is a bug, isn't it?
> ----
> Hiroshi Tachibana

I tried this with our C compiler, and it works the way Hiroshi describes.  I
assume it is a problem with any PCC based C compiler.  Comments, anyone?
(Oh, and I assume you mean "signed" character, as that is the way mine
treated it.  When I changed the value from 257 to 254, the program output
'-2' - which, when you think about it, is pretty much of a 'burn', isn't it?
By the way, I got the program to give correct results by changing "257" to
"(unsigned) 257")
-- 
-Pete Zakel (..!{hplabs,amd,pyramid,ihnp4}!pesnta!valid!pete)

gwyn@BRL.ARPA (VLD/VMB) (04/06/86)

Of course
	printf( "%d\n", (any_expr, 257) );
should print "257\n".  It is not true that all PCC-based compilers
have a problem with this; neither of the ones I normally use does.
Even the 4.2BSD PCC gets this right; Sun must have introduced the bug.

chris@umcp-cs.UUCP (Chris Torek) (04/06/86)

In article <215@valid.UUCP> pete@valid.UUCP (Pete Zakel) writes:
>I tried [printf("%d\n", (0, 257)) and it failed, printing `1'].  I
>assume it is a problem with any PCC based C compiler.

Not so:  On a 4.3-beta Vax compiler, this will print 257.  You
can get around the bug on Suns by forcing the constant to be `long':

	f((0, 257L));

passes 257 to `f'.

This may be related to another bug, where

	f((int)(char)(const));

will not sign extend the constant `const' (variables are properly
sign extended).  Indeed, that problem also goes away if `const' is
a long constant, or if you use

	f((int)(char)(int)(const));

It appears to be the result of an improperly executed attempt at
improving the code generated by small integer constants.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 1415)
UUCP:	seismo!umcp-cs!chris
CSNet:	chris@umcp-cs		ARPA:	chris@mimsy.umd.edu