[net.lang.c] if bug in Ritchie C compiler

CSvax:Pucc-H:Physics:crl (01/26/83)

#N:pur-phy:15700005:000:726
pur-phy!crl    Jan 26 11:02:00 1983

I have just noticed a bug in the Ritchie C compiler (or at least
an example of it being too smart for its own good).  Consider the
following:
	main()
	{
		if (foo()*0);
	}
	
	foo()
	{
		printf("in foo\n");
	}

The compiler thinks:  "Well, foo() * 0 is always false, so I won't
even compile the if statement."

I don't think that this should be the way it compiles, what do you
people think?  (I know no sane person would do this, but I had to
fix some software I got from somewhere else where in a complicated
series of #ifdefs someone had decided that this was the easiest
way to have the if always fail.  YECCH!)

The "bug" does not seem to exist in our version of pcc.

Charles LaBrec
pur-ee!Physics:crl
purdue!Physics:crl

wsh (01/27/83)

**************************************************************************

	I have just noticed a bug in the Ritchie C compiler (or at least
	an example of it being too smart for its own good)...

**************************************************************************

     We quote from the Gospel according to Kernighan and Ritchie (p. 185):
"Otherwise the order of evaluation of expressions is undefined.  In
particular the compiler considers itself free to compute subexpressions
in the order it believes most efficient, even if the subexpressions involve
side effects.  The order in which side effects take place is unspecified.
Expressions involving a commutatiave and associative operator (*, +, &,
|, ^) may be rearranged arbitrarily, even in the presence of parentheses;
to force a particular order of evaluation an explicit temporary must be
used."
     The lesson seems to be that the code cited in the original article
is not portable (assuming that the side effect from foo () is expected),
and that the Ritchie compiler is acting entirely correctly (if only
because the C language specification specifically relieves the compiler
of responsibility for any particular implementation).  Here is a case of
the code (rather than the compiler) being too smart for its own good
(again, assuming that the code expects foo () to be executed).  A
reasonable way to get around this problem is to use the comma operator;
the expression

     if (foo (), 0)

has the desired effect, in a well-defined way.

                                        Willie Heck
                                        abi - holmdel
                                        npoiv!hou5f!wsh

rcj (01/27/83)

	if (foo()*0) ...

INSANITY!!!

The MAD Programmer
alias:  Curtis Jackson	...!floyd!burl!rcj
			...!sb1!burl!rcj
			...!mhuxv!burl!rcj

leichter (01/28/83)

The text you quote explicitly gives the compiler to RE-ARRANGE expressions
and evaluate their component parts in any order it likes.  It DOES NOT, as
it stands, give it permission to skip the evaluation of any part.  I think
if you look up the discussion of, say, & vs. &&, you will find some remarks
to the effect that && only evaluates as much as it needs, but & evaluates
both arguments.  What, then, is one to make of 0&foo()?
							-- Jerry
						decvax!yale-comix!leichter

CSvax:Pucc-H:Physics:crl (01/30/83)

#R:burl:-5400:pur-phy:15700006:000:1755
pur-phy!crl    Jan 29 14:35:00 1983

In bringing this case up originally, I didn't see that the way the
Ritchie compiler optimized the evaluation of the if expression out
would make much of a difference in any *sane* code.  However, in
thinking about it some more, I believe that there is a possibility
that this may come up in some software somewhere.

Suppose one was writing a program that was to be distributed, and
for this reason, you include 2 tunable parameters A and B that
are #define's.  It would then not seem like a potential disaster
to say:
	if (i++ * (A-B) > 20) { 	/* is i incremented? */
		. . .
would it?  Who would expect that if A==B, the i++ would never
be executed at all?  In fact, since I postulated that this code is
distributed, the bug might be just about impossible to track down.
In my case, I was just lucky because it wasn't A-B but a hard-coded
'0'.

Sure programmers are warned about counting on side-effects, but we
all use them when there doesn't seem to be a problem.  The above
would work on pcc, but also on R's cc, except at an installation who
set A=B.  Furthermore, nary a message is printed by either the compiler
or lint about the non-evaluation of the "if" test or the unreachability
of the "then" portion.

So the question remains:  is it a bug, or not?

While it is true that expressions may be re-ordered, I agree with
yale-comix!leichter that the compiler should not be allowed to
*avoid* the evaluation of a non-constant expression.  If A and B
above were variables and not constants, I definitely would not want
a compiler to evaluate (A-B), decide it was == 0, and not perform the
i++.  While it is very clear here that that would be a bug, the two
cases are analogous, at least to me.

Charles LaBrec
pur-ee!Physics:crl
purdue!Physics:crl

sjb (01/31/83)

The reference manual clearly states that ++ has a higher precedence
than -.  Therefore, if the compiler throws the block away because
A==B, it wouldn't seem to be following the rules of precedence.

norskog (02/02/83)

#R:pur-phy:15700005:fortune:16200003:000:155
fortune!norskog    Feb  1 21:39:00 1983

This process is known as "constant folding" and is a part
of any reasonably sophisticated compiler.
En otras palabras, 'tis a feature.

				Lance Norskog