[comp.lang.c] constant expression rules

ggs@ulysses.homer.nj.att.com (Griff Smith) (09/25/87)

A user of our system grumbled recently that our C compiler is broken.
He tried to compile the following on our 4.3BSD CCI POWER 6/32 C
compiler:

int j = ((int )(.5 * 4));

The response from the compiler was

"foo.c", line 1: illegal initialization

I then wrapped a function around it and compiled it on a 4.3BSD VAX
and on the 4.3BSD tahoe compiler.  The VAX produced the following
assembly language fragment:

	movl	$2,-4(fp)	# 0.5 * 4 has been reduced to 2
	movl	-4(fp),r0
	ret

The tahoe did it the hard way:

	.data
	.align	2
L20:
	.long	0x41000000, 0x00000000 # .double 2
	.text
	ldd	L20		# note that .5 * 4 is reduced to 2.0
	cvdl	r0		# convert to long the hard way
	movl	r0,-56(fp)
	movl	-56(fp),r0
	ret#1

I think this explains the problem with constant initialization on the
tahoe compiler; the expression is "too complex".  I also tried the
4.2BSD VAX C compiler and got output similar to the tahoe.

The question is - what is a reasonable level of constant folding that
I can assume when trying to write portable code?  Is this a bug or a
gotcha?  K&R says that I can have almost any set of constants connected
by +, -, *, ?: and a host of others (page 211).
-- 
Griff Smith	AT&T (Bell Laboratories), Murray Hill
Phone:		1-201-582-7736
UUCP:		{allegra|ihnp4}!ulysses!ggs
Internet:	ggs@ulysses.uucp

guy%gorodish@Sun.COM (Guy Harris) (09/26/87)

> The question is - what is a reasonable level of constant folding that
> I can assume when trying to write portable code?  Is this a bug or a
> gotcha?

This is a bug.  Any reasonable and correct compiler will certainly include
float -> int conversions, and *vice versa*, as operations that can be
performed at compile time, as well as the usual sorts of floating-point and
integer operations.

The trouble is that PCC's code for doing folding of conversions of constants at
compile time is very fragile, and if you don't arrange to have things done at
the proper times, PCC ends up seeing trees with conversion operators, rather
than constants, at the root and gets all ticked off at you.  I have seen this
sort of thing break several flavors of PCC (including CCI's 68K compiler; that
one I fixed, for at least some of the cases).  Unfortunately, fixes to one
version may not fix other versions; some of the code in question lives in the
machine-dependent portions of PCC.
	Guy Harris
	{ihnp4, decvax, seismo, decwrl, ...}!sun!guy
	guy@sun.c);g

gwyn@brl-smoke.ARPA (Doug Gwyn ) (09/27/87)

In article <3018@ulysses.homer.nj.att.com> ggs@ulysses.homer.nj.att.com (Griff Smith) writes:
>The question is - what is a reasonable level of constant folding that
>I can assume when trying to write portable code?

The practical answer is, if you need to anticipate the actual behavior
of a wide range of existing C compilers, you cannot count on very much!
Generally, constant expressions involving just integers and the simple
arithmetic operations are handled correctly by C compilers.  Constant
expressions involving much more, for example floating-point and casts,
are only handled correctly by some implementations, although the
forthcoming C standard promises that they are valid in initializers.

henry@utzoo.UUCP (Henry Spencer) (09/29/87)

> The question is - what is a reasonable level of constant folding that
> I can assume when trying to write portable code? ...

Well, read X3J11's latest draft for what you *ought* to be able to assume.
Now, in reality:

	1. Keep It Simple.  Keep It Simple.  Keep It Simple.

	2. Casts were a late addition to the language and to some compilers;
		expect trouble there.

	3. Compile-time floating-point evaluation is another dangerous area,
		especially in cross-compilers.
-- 
"There's a lot more to do in space   |  Henry Spencer @ U of Toronto Zoology
than sending people to Mars." --Bova | {allegra,ihnp4,decvax,utai}!utzoo!henry