[comp.lang.c] Was that a Sun bug?

mark@cci632.UUCP (Mark Stevans) (07/14/87)

The current miasma of text in comp.lang.c reminds me of a bug I saw last
year on a Parallel Computers 4.2bsd system.

The Parallel is a supposedly fault-tolerant machine made out of two Sun-2
CPU boards with some other hardware thrown in.  The software is almost
completely taken from Sun's 4.2bsd: the manuals are Sun, etc..

The following function:

	foo()
	{
		char c = 2;

		if (c == 2)
			printf("c is equal to 2\n");

		if (c == (2 + 1024))
			printf("c is also equal to 1026\n");
	}	

when compiled with Parallel's C compiler would print both messages.  Examining
the assembly language code generated by the compiler revealed that "ccom"
was generating a byte comparison instruction both tests, instead of
extending the character to an int and doing a full-word comparison.

I know that there is no *real* good reason to compare characters against
integral constants that cannot fit inside char variables.  But nevertheless,
I call this a bug.  The Parallel "guru" didn't seem interested in looking
at this.  He hinted that I should read K&R, which annoyed me considerably.
I responded that this did not violate K&R -- it violated rules so basic
they are not covered in K&R: nowhere in K&R does it say that an integer X
cannot be equal to both Y and Z if Y is not equal to Z.

Anyhow, is this a bug, or am I crazy?  Is this a Parallel bug, or does it
exist on Sun 4.2 systems too?

					Mark "Imagining" Stevans
					cci632!mark

ron@topaz.rutgers.edu (Ron Natalie) (07/14/87)

It does not happen on my Sun (3.2).

Point out the following lines in K&R to your rep:

From Appendix A, C Reference Manual

p. 190, sec 7.7 Equality Operators
    The == (equal to) and the != (not equal to) operators are
    exactly equal to the relational operators except for their
    lower precedence.

p. 189, sec 7.6 Relational Operators
    The usual arithmetic converstions are performed.

p. 184. sec 6.6 Arithmetic Conversions
    This pattern will be called the "usual arithmetic conversions"

    First, any operands of type char or short are converted to int.

Hence, both sides should be type int before the comparison is performed.

-Ron

guy%gorodish@Sun.COM (Guy Harris) (07/14/87)

> Anyhow, is this a bug, or am I crazy?  Is this a Parallel bug, or does it
> exist on Sun 4.2 systems too?

From the diagnostics issued by a SunOS 3.2-vintage compiler:

"foo.c", line 8: warning: constant 1026 is out of range of char comparison 
"foo.c", line 8: warning: value coerced to 2 for bug compatibility
"foo.c", line 8: warning: do not expect this coercion in release 4.0

So yes, it is a bug.  I guess somebody complained because their
incorrect code ceased to "work" when the bug was fixed.

The Parallel "guru" is right in the sense that K&R, for whatever
reason, does not explicitly say that "the usual arithmetic
conversions" are performed for relational and equality operators, but
it does list them explicitly for other classes of operators.  I don't
know whether this was done intentionally, to indicate that some other
conversions should be performed, or whether it was just an accidental
omission.  Clearly, *some* conversions must be performed, and the
usual arithmetic conversions would seem to make sense; *narrowing*
one of the operands doesn't seem to make much sense at all.  (The
compiler should be smart enough to do a byte comparison *when it
would give the proper results*.)

The current ANSI C draft, however, *does* say that the usual
arithmetic conversions are performed, which makes more sense; as you
noted, performing the UNusual arithmetic conversions that our
compiler was doing violates the Principle of Least Surprise.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

tim@amdcad.AMD.COM (Tim Olson) (07/15/87)

In article <1429@cci632.UUCP> mark@cci632.UUCP (Mark Stevans) writes:
+-----
| The following function:
| 
| 	foo()
| 	{
| 		char c = 2;
| 
| 		if (c == 2)
| 			printf("c is equal to 2\n");
| 
| 		if (c == (2 + 1024))
| 			printf("c is also equal to 1026\n");
| 	}	
| 
| when compiled with Parallel's C compiler would print both messages.  Examining
| the assembly language code generated by the compiler revealed that "ccom"
| was generating a byte comparison instruction both tests, instead of
| extending the character to an int and doing a full-word comparison.
| 
| I know that there is no *real* good reason to compare characters against
| integral constants that cannot fit inside char variables.  But nevertheless,
| I call this a bug.  The Parallel "guru" didn't seem interested in looking
| at this.  He hinted that I should read K&R, which annoyed me considerably.
| I responded that this did not violate K&R -- it violated rules so basic
| they are not covered in K&R: nowhere in K&R does it say that an integer X
| cannot be equal to both Y and Z if Y is not equal to Z.
+-----
Maybe the "Parallel guru" should read K&R:

	6.6 Arithmetic conversions

	"A great many operators cause conversions and yield result types
	in a similar way.  This pattern will be called the 'usual arithmetic
	conversions.'

	First, any operands of type char or short are converted to int..."


	7.6 Relational operators

	"...The usual arithmetic conversions are performed..."


	7.7 Equality operators

	"The == (equal to) and the != (not equal to) operators are
	exactly analogous to the relational operators..."



	-- Tim Olson
	Advanced Micro Devices
	(tim@amdcad.amd.com)

guy%gorodish@Sun.COM (Guy Harris) (07/15/87)

> 	7.6 Relational operators
> 
> 	"...The usual arithmetic conversions are performed..."

Oops.  I figured it didn't make sense not to do the UAC's, but the
text where it says that, in fact, it's invalid not to do them slipped
my eye.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.com

ron@topaz.rutgers.edu (Ron Natalie) (07/15/87)

> The Parallel "guru" is right in the sense that K&R, for whatever
> reason, does not explicitly say that "the usual arithmetic
> conversions" are performed for relational and equality operators, but

The reference manual in Appendix A of K&R certainly does say that
the "usual arithmetic conversions" are performed for relational and
equality operators.

-Ron

john@frog.UUCP (John Woods, Software) (07/21/87)

In article <1429@cci632.UUCP>, mark@cci632.UUCP (Mark Stevans) writes:
> The current miasma of text in comp.lang.c reminds me of a bug I saw last
> year on a Parallel Computers 4.2bsd system.
> 	foo()
> 	{	char c = 2;
> 		if (c == 2)		printf("c is equal to 2\n");
> 		if (c == (2 + 1024))	printf("c is also equal to 1026\n");
> 	}	
>when compiled with Parallel's C compiler would print both messages...
> The Parallel "guru" didn't seem interested in looking
> at this.  He hinted that I should read K&R, which annoyed me considerably.
> 
> 					Mark "Imagining" Stevans
> 					cci632!mark
Yes, you should definitely read K&R.  For example,

"6.1 Characters and integers
    A character or a short integer may be used wherever an integer may be
used.  In all cases the value is converted to an integer." (page 183 of
the Holy Writ)

You should take a standard head-alignment tool (15 pound crowbar) and a copy
of K&R with you to your next talk with said ``"guru"''.

--
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101
...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA

Doktor of the Forbidden Sciences